This is the code for the statistical analysis for “Vowel Acoustics as Predictors of Speech Intelligibility in Dysarthria.”

Loading Packages


library(rio)
The following rio suggested packages are not installed: ‘csvy’, ‘feather’, ‘fst’, ‘hexView’, ‘readODS’, ‘rmatio’
Use 'install_formats()' to install them
library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
── Attaching packages ─────────────────────────────────────────────── tidyverse 1.3.0 ──
✓ ggplot2 3.3.5     ✓ purrr   0.3.4
✓ tibble  3.1.6     ✓ dplyr   1.0.7
✓ tidyr   1.1.3     ✓ stringr 1.4.0
✓ readr   1.4.0     ✓ forcats 0.5.1
── Conflicts ────────────────────────────────────────────────── tidyverse_conflicts() ──
x dplyr::filter() masks stats::filter()
x dplyr::lag()    masks stats::lag()
library(irr) # install.packages('irr')
Loading required package: lpSolve
library(performance)

Attaching package: ‘performance’

The following object is masked from ‘package:irr’:

    icc
library(car)
Loading required package: carData

Attaching package: ‘car’

The following object is masked from ‘package:dplyr’:

    recode

The following object is masked from ‘package:purrr’:

    some
library(ggpubr)
library("Hmisc") # install.packages('Hmisc')
Loading required package: lattice
Loading required package: survival
Loading required package: Formula

Attaching package: ‘Hmisc’

The following objects are masked from ‘package:dplyr’:

    src, summarize

The following objects are masked from ‘package:base’:

    format.pval, units
library(ggridges)
library(furniture) # install.packages('furniture')
library(gt)

Attaching package: ‘gt’

The following object is masked from ‘package:Hmisc’:

    html
library(patchwork)
library(ks)
library(emuR) # install.packages('emuR')

Attaching package: ‘emuR’

The following object is masked from ‘package:Hmisc’:

    label

The following object is masked from ‘package:car’:

    ellipse

The following object is masked from ‘package:base’:

    norm

Upload Datasets


Reliability <- rio::import("Prepped Data/Reliability Data.csv")
AcousticData <- rio::import("Prepped Data/AcousticMeasures.csv") %>%
  dplyr::mutate(intDiff = VAS - transAcc)

AcousticData <- AcousticData %>%
  dplyr::filter(!grepl("_rel", Speaker)) %>%
  dplyr::select(c(Speaker, Sex, Etiology, vowel_ED_b, VSA_b, autoVSA,
                  Hull_b,Hull_bVSD_25, Hull_bVSD_50, Hull_bVSD_75,
                  VAS, transAcc)) %>%
  dplyr::mutate(Etiology = as.factor(Etiology),
                Sex = as.factor(Sex),
                Speaker = as.factor(Speaker))

Listeners <- rio::import("Prepped Data/Listener_Demographics.csv") %>%
  dplyr::select(!c(StartDate:proloficID, Q2.4_6_TEXT, Q3.2_8_TEXT, AudioCheck:EP3))

Listeners$race[Listeners$Q3.3_7_TEXT == "Native American/ African amercing"] <- "Biracial or Multiracial"

Inter-rater Reliability

Two raters (the first two authors) completed vowel segmentation for the speakers. To calculate inter-rater reliability, 20% of the speakers were segmented again by the other rater. Two-way intraclass coefficients were computed for the extracted F1 and F2 from the temporal midpoint of the vowel segments. Since only one set of ratings will be used in the data analysis, we focus on the single ICC results and interpretation. However, we also report the average ICC values to be comprehensive.


## Creating new data frames to calculate ICC for extracted F1 and F2 values

F1_Rel <- Reliability %>%
  dplyr::select(c(F1, F1_rel))

F2_Rel <- Reliability %>%
  dplyr::select(c(F2, F2_rel))
  
## Single ICC for F1
Single_F1 <- irr::icc(F1_Rel, model = "twoway", type = "agreement", unit = "single")

## Average ICC for F1
Average_F1 <- irr::icc(F1_Rel, model = "twoway", type = "agreement", unit = "average")

## Single ICC for F2
Single_F2 <- irr::icc(F2_Rel, model = "twoway", type = "agreement", unit = "single")

## Average ICC for F2
Average_F2 <- irr::icc(F2_Rel, model = "twoway", type = "agreement", unit = "average")

## Inter-rater reliability results and interpretation

print(paste("Single ICC for F1 is ", round(Single_F1$value, digits = 3), ". ", 
            "The 95% CI is [", round(Single_F1$lbound, digits = 3), " - ", round(Single_F1$ubound, digits = 3), "].", sep = ""))
[1] "Single ICC for F1 is 0.866. The 95% CI is [0.837 - 0.89]."
print(paste("Single ICC for F2 is ", round(Single_F2$value, digits = 3), ". ", 
            "The 95% CI is [", round(Single_F2$lbound, digits = 3), " - ", round(Single_F2$ubound, digits = 3), "].", sep = ""))
[1] "Single ICC for F2 is 0.931. The 95% CI is [0.916 - 0.944]."
print(paste("Average ICC for F1 is ", round(Average_F1$value, digits = 3), ". ", 
            "The 95% CI is [", round(Average_F1$lbound, digits = 3), " - ", round(Average_F1$ubound, digits = 3), "].", sep = ""))
[1] "Average ICC for F1 is 0.928. The 95% CI is [0.911 - 0.942]."
print(paste("Average ICC for F2 is ", round(Average_F2$value, digits = 3), ". ", 
            "The 95% CI is [", round(Average_F2$lbound, digits = 3), " - ", round(Average_F2$ubound, digits = 3), "].", sep = ""))
[1] "Average ICC for F2 is 0.964. The 95% CI is [0.956 - 0.971]."
print("Thus, interrater reliability for the extracted F1 and F2 values from the vowel segments was good to excellent.")
[1] "Thus, interrater reliability for the extracted F1 and F2 values from the vowel segments was good to excellent."
## Removing extra data frames from environment

rm(F1_Rel, F2_Rel, Reliability, Single_F1, Single_F2, Average_F1, Average_F2)

Descriptive Statistics

Correlations

CorrMatrix <- AcousticData %>%
  dplyr::select(VSA_b, vowel_ED_b, autoVSA, Hull_b, Hull_bVSD_25, Hull_bVSD_75, VAS, transAcc) %>%
  as.matrix() %>%
  Hmisc::rcorr()

CorrMatrixP <- CorrMatrix$P < .05

CorrMatrix <- CorrMatrix$r

stats::cor.test(AcousticData$VSA_b, AcousticData$vowel_ED_b, method = "pearson")

    Pearson's product-moment correlation

data:  AcousticData$VSA_b and AcousticData$vowel_ED_b
t = 6.5285, df = 38, p-value = 1.076e-07
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 0.5372669 0.8468014
sample estimates:
      cor 
0.7270881 
stats::cor.test(AcousticData$Hull_b, AcousticData$Hull_bVSD_25, method = "pearson")

    Pearson's product-moment correlation

data:  AcousticData$Hull_b and AcousticData$Hull_bVSD_25
t = 9.4906, df = 38, p-value = 1.43e-11
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 0.7135136 0.9119080
sample estimates:
     cor 
0.838625 
stats::cor.test(AcousticData$Hull_b, AcousticData$autoVSA, method = "pearson")

    Pearson's product-moment correlation

data:  AcousticData$Hull_b and AcousticData$autoVSA
t = 11.103, df = 38, p-value = 1.723e-13
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 0.7734205 0.9319757
sample estimates:
      cor 
0.8742893 
write.csv(CorrMatrix, file = "Tables/Correlation Matrix.csv")
rm(CorrMatrix)

Research Q1: Modeling Intelligibility

Orthographic Transcriptions

Model 1


# Specifying Model 1

OT_Model1 <- lm(transAcc ~ Hull_bVSD_25, data = AcousticData)

## Model 1 Assumptions 

performance::check_model(OT_Model1)


## Model 1 Summary

summary(OT_Model1)

Call:
lm(formula = transAcc ~ Hull_bVSD_25, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-47.896 -14.090   5.996  17.470  36.105 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)   48.2973     9.7372   4.960  1.5e-05 ***
Hull_bVSD_25   0.6417     0.5663   1.133    0.264    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 23.83 on 38 degrees of freedom
Multiple R-squared:  0.03268,   Adjusted R-squared:  0.007224 
F-statistic: 1.284 on 1 and 38 DF,  p-value: 0.2643

Model 2


## Specifying Model 2

OT_Model2 <- lm(transAcc ~ Hull_bVSD_25 + Hull_bVSD_75, data = AcousticData)

## Model 2 Assumption Check

performance::check_model(OT_Model2)


## Model 2 Summary

summary(OT_Model2)

Call:
lm(formula = transAcc ~ Hull_bVSD_25 + Hull_bVSD_75, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-48.854 -13.962   5.567  16.758  36.257 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)   47.3374    10.3316   4.582 5.09e-05 ***
Hull_bVSD_25   0.8045     0.7781   1.034    0.308    
Hull_bVSD_75  -0.7188     2.3225  -0.309    0.759    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 24.11 on 37 degrees of freedom
Multiple R-squared:  0.03518,   Adjusted R-squared:  -0.01698 
F-statistic: 0.6745 on 2 and 37 DF,  p-value: 0.5156
## Model 1 and Model 2 Comparison

anova(OT_Model1, OT_Model2)
Analysis of Variance Table

Model 1: transAcc ~ Hull_bVSD_25
Model 2: transAcc ~ Hull_bVSD_25 + Hull_bVSD_75
  Res.Df   RSS Df Sum of Sq      F Pr(>F)
1     38 21570                           
2     37 21514  1    55.696 0.0958 0.7587

Model 3a


## Specifying Model 3

OT_Model3a <- lm(transAcc ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b, data = AcousticData)

## Model 3 Assumption Check

performance::check_model(OT_Model3a)
performance::check_collinearity(OT_Model3a)


## Model 3 Summary

summary(OT_Model3a)

## Model 2 and Model 3 Comparison

anova(OT_Model2, OT_Model3a)

Model 3b


## Specifying Model 3

OT_Model3b <- lm(transAcc ~ Hull_bVSD_75 + Hull_b, data = AcousticData)

## Model 3 Assumption Check

performance::check_model(OT_Model3b)

performance::check_collinearity(OT_Model3b)
# Check for Multicollinearity

Low Correlation

         Term  VIF Increased SE Tolerance
 Hull_bVSD_75 1.26         1.12      0.79
       Hull_b 1.26         1.12      0.79
## Model 3 Summary

summary(OT_Model3b)

Call:
lm(formula = transAcc ~ Hull_bVSD_75 + Hull_b, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-54.371 -12.860   5.038  17.725  31.609 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)  
(Intercept)   33.2337    13.9973   2.374   0.0229 *
Hull_bVSD_75  -0.6193     1.8702  -0.331   0.7424  
Hull_b         0.8605     0.4809   1.789   0.0818 .
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 23.47 on 37 degrees of freedom
Multiple R-squared:  0.08635,   Adjusted R-squared:  0.03697 
F-statistic: 1.749 on 2 and 37 DF,  p-value: 0.1881

Model 4a


## Specifying Model 4

OT_Model4a <- lm(transAcc ~ Hull_bVSD_75 + Hull_b + autoVSA, data = AcousticData)

## Model 4 Assumption Check

performance::check_model(OT_Model4a)

performance::check_collinearity(OT_Model4a)
# Check for Multicollinearity

Low Correlation

         Term  VIF Increased SE Tolerance
 Hull_bVSD_75 1.31         1.15      0.76
      autoVSA 4.41         2.10      0.23

Moderate Correlation

   Term  VIF Increased SE Tolerance
 Hull_b 5.02         2.24      0.20
## Model 4 Summary

summary(OT_Model4a)

Call:
lm(formula = transAcc ~ Hull_bVSD_75 + Hull_b + autoVSA, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-46.729  -9.736   2.928  13.425  32.586 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)   
(Intercept)   33.0695    13.0702   2.530  0.01592 * 
Hull_bVSD_75  -1.5011     1.7806  -0.843  0.40478   
Hull_b         2.8262     0.8956   3.156  0.00323 **
autoVSA       -5.6340     2.2208  -2.537  0.01566 * 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 21.91 on 36 degrees of freedom
Multiple R-squared:  0.2249,    Adjusted R-squared:  0.1603 
F-statistic: 3.482 on 3 and 36 DF,  p-value: 0.02561
## Model 3 and Model 4 Comparison

anova(OT_Model3b, OT_Model4a)
Analysis of Variance Table

Model 1: transAcc ~ Hull_bVSD_75 + Hull_b
Model 2: transAcc ~ Hull_bVSD_75 + Hull_b + autoVSA
  Res.Df   RSS Df Sum of Sq      F  Pr(>F)  
1     37 20373                              
2     36 17283  1    3089.9 6.4361 0.01566 *
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Model 4b


## Specifying Model 4

OT_Model4b <- lm(transAcc ~ Hull_bVSD_75 + autoVSA, data = AcousticData)

## Model 4 Assumption Check

performance::check_model(OT_Model4b)

performance::check_collinearity(OT_Model4b)
# Check for Multicollinearity

Low Correlation

         Term  VIF Increased SE Tolerance
 Hull_bVSD_75 1.11         1.05      0.90
      autoVSA 1.11         1.05      0.90
## Model 4 Summary

summary(OT_Model4b)

Call:
lm(formula = transAcc ~ Hull_bVSD_75 + autoVSA, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-49.900 -15.387   6.626  17.304  32.102 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)   52.3999    12.8682   4.072 0.000236 ***
Hull_bVSD_75   0.7069     1.8248   0.387 0.700710    
autoVSA        0.4296     1.2411   0.346 0.731176    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 24.42 on 37 degrees of freedom
Multiple R-squared:  0.0105,    Adjusted R-squared:  -0.04298 
F-statistic: 0.1964 on 2 and 37 DF,  p-value: 0.8225

Model 5


## Specifying Model 5

OT_Model5 <- lm(transAcc ~ Hull_bVSD_75 + autoVSA + VSA_b, data = AcousticData)

## Model 4 Assumption Check

performance::check_model(OT_Model5)

performance::check_collinearity(OT_Model5)
# Check for Multicollinearity

Low Correlation

         Term  VIF Increased SE Tolerance
 Hull_bVSD_75 1.15         1.07      0.87
      autoVSA 1.20         1.09      0.84
        VSA_b 1.17         1.08      0.85
## Model 4 Summary

summary(OT_Model5)

Call:
lm(formula = transAcc ~ Hull_bVSD_75 + autoVSA + VSA_b, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-46.674 -12.643   4.169  15.099  34.515 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)   
(Intercept)   38.1376    11.9031   3.204  0.00284 **
Hull_bVSD_75  -0.4416     1.6222  -0.272  0.78701   
autoVSA       -0.6501     1.1229  -0.579  0.56622   
VSA_b          6.3560     1.7810   3.569  0.00104 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 21.28 on 36 degrees of freedom
Multiple R-squared:  0.2691,    Adjusted R-squared:  0.2082 
F-statistic: 4.418 on 3 and 36 DF,  p-value: 0.009589
## Model 3 and Model 4 Comparison

anova(OT_Model4b, OT_Model5)
Analysis of Variance Table

Model 1: transAcc ~ Hull_bVSD_75 + autoVSA
Model 2: transAcc ~ Hull_bVSD_75 + autoVSA + VSA_b
  Res.Df   RSS Df Sum of Sq      F   Pr(>F)   
1     37 22064                                
2     36 16298  1    5766.1 12.736 0.001038 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Model 6


## Specifying Model 6

OT_Model6 <- lm(transAcc ~ Hull_bVSD_75 + autoVSA + VSA_b + vowel_ED_b, data = AcousticData)

## Model 6 Assumption Check

performance::check_model(OT_Model6)

performance::check_collinearity(OT_Model6)
# Check for Multicollinearity

Low Correlation

         Term  VIF Increased SE Tolerance
 Hull_bVSD_75 1.20         1.10      0.83
      autoVSA 1.31         1.15      0.76
        VSA_b 2.30         1.52      0.43
   vowel_ED_b 2.36         1.54      0.42
## Model 6 Summary

summary(OT_Model6)

Call:
lm(formula = transAcc ~ Hull_bVSD_75 + autoVSA + VSA_b + vowel_ED_b, 
    data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-45.023 -13.342   2.208  17.093  32.847 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)  
(Intercept)   26.9818    20.5367   1.314   0.1974  
Hull_bVSD_75  -0.2272     1.6659  -0.136   0.8923  
autoVSA       -0.8851     1.1848  -0.747   0.4600  
VSA_b          5.1767     2.5152   2.058   0.0471 *
vowel_ED_b     8.9714    13.4053   0.669   0.5077  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 21.44 on 35 degrees of freedom
Multiple R-squared:  0.2783,    Adjusted R-squared:  0.1958 
F-statistic: 3.375 on 4 and 35 DF,  p-value: 0.01948
## Model 5 and Model 6 Comparison

anova(OT_Model5, OT_Model6)
Analysis of Variance Table

Model 1: transAcc ~ Hull_bVSD_75 + autoVSA + VSA_b
Model 2: transAcc ~ Hull_bVSD_75 + autoVSA + VSA_b + vowel_ED_b
  Res.Df   RSS Df Sum of Sq      F Pr(>F)
1     36 16298                           
2     35 16092  1    205.93 0.4479 0.5077

Final Model


## Specifying Final Model

OT_Model_final <- lm(transAcc ~ VSA_b, data = AcousticData)

## Final Model Assumption Check

performance::check_model(OT_Model_final)


## Final Model Summary

summary(OT_Model_final)

Call:
lm(formula = transAcc ~ VSA_b, data = AcousticData)

Residuals:
   Min     1Q Median     3Q    Max 
-46.72 -12.69   2.97  14.37  35.39 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)   32.508      7.857   4.138 0.000187 ***
VSA_b          5.872      1.613   3.641 0.000807 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 20.86 on 38 degrees of freedom
Multiple R-squared:  0.2586,    Adjusted R-squared:  0.2391 
F-statistic: 13.25 on 1 and 38 DF,  p-value: 0.0008068
confint(OT_Model_final)
                2.5 %    97.5 %
(Intercept) 16.602765 48.413532
VSA_b        2.606927  9.137097

VAS Models

Model 1


# Specifying Model 1

VAS_Model1 <- lm(VAS ~ Hull_bVSD_25, data = AcousticData)

## Model 1 Assumptions 

performance::check_model(VAS_Model1)

## Model 1 Summary

summary(VAS_Model1)

Model 2


## Specifying Model 2

VAS_Model2 <- lm(VAS ~ Hull_bVSD_25 + Hull_bVSD_75, data = AcousticData)

## Model 2 Assumption Check

performance::check_model(VAS_Model2)


## Model 2 Summary

summary(VAS_Model2)

Call:
lm(formula = VAS ~ Hull_bVSD_25 + Hull_bVSD_75, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-47.850 -16.576   8.382  19.448  37.237 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)   42.3384    11.4211   3.707 0.000684 ***
Hull_bVSD_25   0.6376     0.8602   0.741 0.463195    
Hull_bVSD_75  -0.2204     2.5674  -0.086 0.932036    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 26.66 on 37 degrees of freedom
Multiple R-squared:  0.02291,   Adjusted R-squared:  -0.0299 
F-statistic: 0.4338 on 2 and 37 DF,  p-value: 0.6513
## Model 1 and Model 2 Comparison

anova(VAS_Model1, VAS_Model2)
Analysis of Variance Table

Model 1: VAS ~ Hull_bVSD_25
Model 2: VAS ~ Hull_bVSD_25 + Hull_bVSD_75
  Res.Df   RSS Df Sum of Sq      F Pr(>F)
1     38 26296                           
2     37 26291  1     5.239 0.0074  0.932

Model 3a


## Specifying Model 3

VAS_Model3a <- lm(VAS ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b, data = AcousticData)

## Model 3 Assumption Check

performance::check_model(VAS_Model3a)

performance::check_collinearity(VAS_Model3a)
# Check for Multicollinearity

Low Correlation

         Term  VIF Increased SE Tolerance
 Hull_bVSD_75 2.00         1.41      0.50
       Hull_b 3.65         1.91      0.27

Moderate Correlation

         Term  VIF Increased SE Tolerance
 Hull_bVSD_25 5.33         2.31      0.19
## Model 3 Summary

summary(VAS_Model3a)

Call:
lm(formula = VAS ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-56.444 -18.989   6.121  18.036  32.281 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)
(Intercept)   25.0400    16.0599   1.559    0.128
Hull_bVSD_25  -1.1164     1.4389  -0.776    0.443
Hull_bVSD_75   0.8805     2.6280   0.335    0.740
Hull_b         1.3770     0.9139   1.507    0.141

Residual standard error: 26.21 on 36 degrees of freedom
Multiple R-squared:  0.08087,   Adjusted R-squared:  0.00428 
F-statistic: 1.056 on 3 and 36 DF,  p-value: 0.3799
## Model 2 and Model 3 Comparison

anova(VAS_Model2, VAS_Model3a)
Analysis of Variance Table

Model 1: VAS ~ Hull_bVSD_25 + Hull_bVSD_75
Model 2: VAS ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b
  Res.Df   RSS Df Sum of Sq      F Pr(>F)
1     37 26291                           
2     36 24731  1    1559.6 2.2702 0.1406

Model 3b


## Specifying Model 3b

VAS_Model3b <- lm(VAS ~  Hull_bVSD_75 + Hull_b, data = AcousticData)

## Model 3 Assumption Check

performance::check_model(VAS_Model3b)

performance::check_collinearity(VAS_Model3b)
# Check for Multicollinearity

Low Correlation

         Term  VIF Increased SE Tolerance
 Hull_bVSD_75 1.26         1.12      0.79
       Hull_b 1.26         1.12      0.79
## Model 3 Summary

summary(VAS_Model3b)

Call:
lm(formula = VAS ~ Hull_bVSD_75 + Hull_b, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-53.356 -19.394   8.036  21.298  33.412 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)  
(Intercept)   27.8884    15.5503   1.793   0.0811 .
Hull_bVSD_75  -0.3567     2.0777  -0.172   0.8646  
Hull_b         0.8034     0.5343   1.504   0.1412  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 26.07 on 37 degrees of freedom
Multiple R-squared:  0.0655,    Adjusted R-squared:  0.01499 
F-statistic: 1.297 on 2 and 37 DF,  p-value: 0.2855

Model 4a


## Specifying Model 4

VAS_Model4a <- lm(VAS ~ Hull_bVSD_75 + autoVSA + Hull_b, data = AcousticData)

## Model 4 Assumption Check

performance::check_model(VAS_Model4a)

performance::check_collinearity(VAS_Model4a)
# Check for Multicollinearity

Low Correlation

         Term  VIF Increased SE Tolerance
 Hull_bVSD_75 1.31         1.15      0.76
      autoVSA 4.41         2.10      0.23

Moderate Correlation

   Term  VIF Increased SE Tolerance
 Hull_b 5.02         2.24      0.20
## Model 4 Summary

summary(VAS_Model4a)

Call:
lm(formula = VAS ~ Hull_bVSD_75 + autoVSA + Hull_b, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-51.912 -20.901   3.669  16.070  40.028 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)   
(Intercept)   27.7029    14.4764   1.914  0.06364 . 
Hull_bVSD_75  -1.3527     1.9721  -0.686  0.49717   
autoVSA       -6.3639     2.4597  -2.587  0.01386 * 
Hull_b         3.0238     0.9919   3.048  0.00429 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 24.27 on 36 degrees of freedom
Multiple R-squared:  0.212, Adjusted R-squared:  0.1464 
F-statistic: 3.229 on 3 and 36 DF,  p-value: 0.03365
## Model 3 and Model 4 Comparison

anova(VAS_Model3b, VAS_Model4a)
Analysis of Variance Table

Model 1: VAS ~ Hull_bVSD_75 + Hull_b
Model 2: VAS ~ Hull_bVSD_75 + autoVSA + Hull_b
  Res.Df   RSS Df Sum of Sq      F  Pr(>F)  
1     37 25145                              
2     36 21202  1    3942.4 6.6939 0.01386 *
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Model 4b


## Specifying Model 4

VAS_Model4b <- lm(VAS ~ Hull_bVSD_75 + autoVSA, data = AcousticData)

## Model 4 Assumption Check

performance::check_model(VAS_Model4b)

performance::check_collinearity(VAS_Model4b)
# Check for Multicollinearity

Low Correlation

         Term  VIF Increased SE Tolerance
 Hull_bVSD_75 1.11         1.05      0.90
      autoVSA 1.11         1.05      0.90
## Model 4 Summary

summary(VAS_Model4b)

Call:
lm(formula = VAS ~ Hull_bVSD_75 + autoVSA, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-47.697 -17.980   9.493  20.999  36.709 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)   
(Intercept)   48.3844    14.1490   3.420  0.00154 **
Hull_bVSD_75   1.0096     2.0065   0.503  0.61783   
autoVSA        0.1236     1.3646   0.091  0.92834   
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 26.85 on 37 degrees of freedom
Multiple R-squared:  0.00862,   Adjusted R-squared:  -0.04497 
F-statistic: 0.1608 on 2 and 37 DF,  p-value: 0.852

Model 5


## Specifying Model 5

VAS_Model5 <- lm(VAS ~ Hull_bVSD_75 + autoVSA + VSA_b, data = AcousticData)

## Model 5 Assumption Check

performance::check_model(VAS_Model5)


## Model 5 Summary

summary(VAS_Model5)

Call:
lm(formula = VAS ~ Hull_bVSD_75 + autoVSA + VSA_b, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-44.376 -19.256   5.331  18.101  42.048 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)   
(Intercept)   33.1721    13.2237   2.509  0.01677 * 
Hull_bVSD_75  -0.2154     1.8022  -0.120  0.90554   
autoVSA       -1.0281     1.2475  -0.824  0.41529   
VSA_b          6.7794     1.9786   3.426  0.00154 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 23.64 on 36 degrees of freedom
Multiple R-squared:  0.2524,    Adjusted R-squared:  0.1901 
F-statistic: 4.052 on 3 and 36 DF,  p-value: 0.01401
## Model 4 and Model 5 Comparison

anova(VAS_Model4b, VAS_Model5)
Analysis of Variance Table

Model 1: VAS ~ Hull_bVSD_75 + autoVSA
Model 2: VAS ~ Hull_bVSD_75 + autoVSA + VSA_b
  Res.Df   RSS Df Sum of Sq     F   Pr(>F)   
1     37 26675                               
2     36 20115  1    6559.9 11.74 0.001545 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Model 6


## Specifying Model 6

VAS_Model6 <- lm(VAS ~ Hull_bVSD_75 + autoVSA + VSA_b + vowel_ED_b, data = AcousticData)

## Model 6 Assumption Check

performance::check_model(VAS_Model6)


## Model 6 Summary

summary(VAS_Model6)

Call:
lm(formula = VAS ~ Hull_bVSD_75 + autoVSA + VSA_b + vowel_ED_b, 
    data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-42.388 -15.904   5.524  18.013  40.040 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)  
(Intercept)  19.74662   22.78983   0.866    0.392  
Hull_bVSD_75  0.04266    1.84869   0.023    0.982  
autoVSA      -1.31095    1.31483  -0.997    0.326  
VSA_b         5.36014    2.79118   1.920    0.063 .
vowel_ED_b   10.79666   14.87603   0.726    0.473  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 23.8 on 35 degrees of freedom
Multiple R-squared:  0.2635,    Adjusted R-squared:  0.1793 
F-statistic: 3.131 on 4 and 35 DF,  p-value: 0.02658
## Model 5 and Model 6 Comparison

anova(VAS_Model5, VAS_Model6)
Analysis of Variance Table

Model 1: VAS ~ Hull_bVSD_75 + autoVSA + VSA_b
Model 2: VAS ~ Hull_bVSD_75 + autoVSA + VSA_b + vowel_ED_b
  Res.Df   RSS Df Sum of Sq      F Pr(>F)
1     36 20115                           
2     35 19817  1    298.25 0.5268 0.4728

Final Model


## Specifying Final Model

VAS_Model_final <- lm(VAS ~ VSA_b, data = AcousticData)

## Final Model Assumption Check

performance::check_model(VAS_Model_final)


## Final Model Summary

summary(VAS_Model_final)

Call:
lm(formula = VAS ~ VSA_b, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-44.956 -15.943   6.754  17.153  43.062 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)   
(Intercept)   24.703      8.761   2.820  0.00760 **
VSA_b          6.163      1.798   3.427  0.00148 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 23.26 on 38 degrees of freedom
Multiple R-squared:  0.2361,    Adjusted R-squared:  0.216 
F-statistic: 11.74 on 1 and 38 DF,  p-value: 0.001482
confint(VAS_Model_final)
               2.5 %    97.5 %
(Intercept) 6.966936 42.438084
VSA_b       2.521887  9.803467

Research Q2: Relationship between OT and VAS

Model 1


# Specify Model

OT_VAS_model <- lm(transAcc ~ VAS*Etiology + VAS*Sex, data = AcousticData)

# Assumption Check

performance::check_model(OT_VAS_model)

# Model Results

summary(OT_VAS_model)

Final Linear Model


# Specify Final Model

OT_VAS_final <- lm(transAcc ~ VAS, data = AcousticData)

confint(OT_VAS_final)

# Model Results

summary(OT_VAS_final)

Corner Dispersion

Looking at corner dispersion as the sole predictor.


# Specify Final Model

OT_cornDisp <- lm(transAcc ~ vowel_ED_b, data = AcousticData)
summary(OT_cornDisp)

Call:
lm(formula = transAcc ~ vowel_ED_b, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-53.949 -10.348   4.268  14.982  25.903 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)   
(Intercept)    6.227     18.611   0.335  0.73977   
vowel_ED_b    25.564      8.946   2.857  0.00689 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 21.98 on 38 degrees of freedom
Multiple R-squared:  0.1769,    Adjusted R-squared:  0.1552 
F-statistic: 8.165 on 1 and 38 DF,  p-value: 0.006891
VAS_cornDisp <- lm(VAS ~ vowel_ED_b, data = AcousticData)
summary(VAS_cornDisp)

Call:
lm(formula = VAS ~ vowel_ED_b, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-52.146 -13.413   7.142  18.719  32.964 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)  
(Intercept)   -2.859     20.636  -0.139   0.8905  
vowel_ED_b    26.819      9.920   2.704   0.0102 *
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 24.37 on 38 degrees of freedom
Multiple R-squared:  0.1613,    Adjusted R-squared:  0.1393 
F-statistic:  7.31 on 1 and 38 DF,  p-value: 0.0102

Manuscript Tables

##Descriptives Table

gtData <- AcousticData %>%
  rbind(.,AcousticData %>%
          dplyr::mutate(Etiology = "All Etiologies")) %>%
  rbind(.,AcousticData %>%
          rbind(.,AcousticData %>%
          dplyr::mutate(Etiology = "All Etiologies")) %>%
          dplyr::mutate(Sex = "All")) %>%
  dplyr::mutate(Sex = as.factor(Sex),
                Etiology = as.factor(Etiology)) %>%
  dplyr::group_by(Sex, Etiology) %>%
  dplyr::summarize(VSA_mean = mean(VSA_b, na.rm =T), VSA_sd = sd(VSA_b, na.rm = T),
                   Disp_mean = mean(vowel_ED_b, na.rm =T), Disp_sd = sd(vowel_ED_b, na.rm =T),
                   autoVSA_mean = mean(autoVSA, na.rm =T), autoVSA_sd = sd(autoVSA, na.rm = T),
                   Hull_mean = mean(Hull_b, na.rm =T), Hull_sd = sd(Hull_b, na.rm =T),
                   VSD25_mean = mean(Hull_bVSD_25, na.rm =T), VSD25_sd = sd(Hull_bVSD_25, na.rm =T),
                   VSD50_mean = mean(Hull_bVSD_50, na.rm =T), VSD50_sd = sd(Hull_bVSD_50, na.rm =T),
                   VSD75_mean = mean(Hull_bVSD_75, na.rm =T), VSD75_sd = sd(Hull_bVSD_75, na.rm =T),
                   VAS_mean = mean(VAS, na.rm =T), VAS_sd = sd(VAS, na.rm =T),
                   OT_mean = mean(transAcc, na.rm =T), OT_sd = sd(transAcc, na.rm =T)) %>%
  pivot_longer(cols = VSA_mean:OT_sd, names_to = "Measure",
               values_to = "Value") %>%
  dplyr::mutate(Value = round(Value, digits = 2),
                meanSD = ifelse(grepl("_mean",Measure),"M","sd"),
                Measure = gsub("_mean","",Measure),
                Measure = gsub("_sd","",Measure),
                Etiology = paste(Etiology,meanSD, sep = "_"),
                Sex = case_when(
                  Sex == "All" ~ "All Speakers",
                  Sex == "M" ~ "Male Speakers",
                  Sex == "F" ~ "Female Speakers"
                )) %>%
  dplyr::select(!meanSD) %>%
  pivot_wider(names_from = Etiology, values_from = "Value") %>%
  dplyr::filter(Measure != "VSD50")

gtData %>%
  gt::gt(
    rowname_col = "Measure",
    groupname_col = "Sex",
  ) %>%
  fmt_number(
    columns = 'All Etiologies_M':PD_sd,
    decimals = 2
  ) %>%
  tab_spanner(
    label = "All Etiologies",
    columns = c('All Etiologies_M', 'All Etiologies_sd')
  ) %>%
    tab_spanner(
    label = "ALS",
    columns = c(ALS_M, ALS_sd)
  ) %>%
  tab_spanner(
    label = "PD",
    columns = c(PD_M, PD_sd)
  ) %>%
  tab_spanner(
    label = "HD",
    columns = c(HD_M, HD_sd)
  ) %>%
  tab_spanner(
    label = "Ataxic",
    columns = c(Ataxic_M, Ataxic_sd)
  ) %>%
  gt::cols_move_to_start(
    columns = c('All Etiologies_M','All Etiologies_sd')
  ) %>%
  row_group_order(
    groups = c("All Speakers", "Female Speakers", "Male Speakers")
    ) %>%
  cols_label(
     'All Etiologies_M' = "M",
     'All Etiologies_sd' = "SD",
     ALS_M = "M",
     ALS_sd = "SD",
     PD_M = "M",
     PD_sd = "SD",
     HD_M = "M",
     HD_sd = "SD",
     Ataxic_M = "M",
     Ataxic_sd = "SD"
  ) %>%
  gtsave("DescriptivesTable.html", path = "Tables")

OT Model

sjPlot::tab_model(OT_Model1,OT_Model2,OT_Model3,
                  OT_Model4, OT_Model5,OT_Model6, OT_Model_final,
                  show.ci = F,
                  p.style = "stars",
                  file = "Tables/OT Models.html")

VAS Model

sjPlot::tab_model(VAS_Model1,
                  VAS_Model2,
                  VAS_Model3,
                  VAS_Model4,
                  VAS_Model5,
                  VAS_Model6,
                  VAS_Model_final,
                  show.ci = F,
                  p.style = "stars",
                  file = "Tables/VAS Models.html")

OT vs. VAS

sjPlot::tab_model(OT_VAS_model,OT_VAS_final,
                  show.ci = F,
                  show.reflvl = TRUE,
                  p.style = "stars",
                  file = "Tables/OT and VAS Comparison.html")

Manuscript Figures

Example Measures

formantColor <- "grey"
formantAlpha <- .95
lineColor <- "white"
lineAlpha <- .8

vowelData <- rio::import("Prepped Data/Vowel Data.csv") %>%
  dplyr::filter(Speaker == "AF8")

  Pitch_PRAAT <- list.files(path = paste("Prepped Data/Example Data/", sep = ""), 
                              pattern = ".Pitch", ignore.case = T) %>%
    paste("Prepped Data/Example Data/",., sep = "") %>%
    read.delim(., header = F) %>%
    dplyr::rename(Pitch = V1) %>%
    dplyr::mutate(Pitch = gsub("--undefined--",NA,Pitch),
                  Pitch = as.numeric(Pitch))
  
  Formants_PRAAT <- list.files(path = paste("Prepped Data/Example Data/", sep = ""), 
                              pattern = "_Formant", ignore.case = T) %>%
    paste("Prepped Data/Example Data/",., sep = "") %>%
    read.delim(., header = T) %>%
    dplyr::select(!c(nformants, B1.Hz., B2.Hz., B3.Hz., F4.Hz., B4.Hz., F5.Hz., B5.Hz.)) %>%
    dplyr::rename(Time_s = time.s.,
                  F1_Hz = F1.Hz.,
                  F2_Hz = F2.Hz.,
                  F3_Hz = F3.Hz.) %>%
    dplyr::mutate(F1_Hz = ifelse(F1_Hz == 0, NA, F1_Hz),
                  F2_Hz = ifelse(F2_Hz == 0, NA, F2_Hz),
                  F3_Hz = ifelse(F3_Hz == 0, NA, F3_Hz)) %>%
    dplyr::mutate(F1_Hz = as.numeric(F1_Hz),
                  F2_Hz = as.numeric(F2_Hz),
                  F3_Hz = suppressWarnings(as.numeric(F3_Hz)),
                  Time_ms = Time_s / 1000,
                  F1_kHz = F1_Hz / 1000,
                  F2_kHz = F2_Hz / 1000,
                  F3_kHz = F3_Hz / 1000) %>%
    dplyr::select(!Time_s) %>%
    dplyr::relocate(Time_ms, .before = F1_Hz) %>%
    cbind(.,Pitch_PRAAT)
  
  c <- 2
  while(c < NROW(Formants_PRAAT)){
    Formants_PRAAT$F1_Hz[c] <- ifelse(is.na(Formants_PRAAT$F1_Hz[c-1]) &&
                                        is.na(Formants_PRAAT$F1_Hz[c+1]),
                                      NA,
                                      Formants_PRAAT$F1_Hz[c])
    Formants_PRAAT$F2_Hz[c] <- ifelse(is.na(Formants_PRAAT$F2_Hz[c-1]) &&
                                        is.na(Formants_PRAAT$F2_Hz[c+1]),
                                      NA,
                                      Formants_PRAAT$F2_Hz[c])
    c <- c + 1
  }
  rm(c)
  
  Formants_PRAAT <- Formants_PRAAT %>%
    dplyr::filter(!is.na(Pitch)) %>%
    dplyr::mutate(F1_mad = (abs(F1_Hz - median(F1_Hz))/ mad(F1_Hz, constant = 1.4826)) > 2.5,
                  F2_mad = (abs(F2_Hz - median(F2_Hz))/ mad(F2_Hz, constant = 1.4826)) > 2.5) %>%
    dplyr::filter(F1_mad == FALSE & F2_mad == FALSE) %>%
    dplyr::mutate(mDist = mahalanobis(cbind(.$F1_Hz, .$F2_Hz),
                                      colMeans(cbind(.$F1_Hz, .$F2_Hz)),
                                      cov = cov(cbind(.$F1_Hz, .$F2_Hz))),
                  mDist_sd = abs(scale(mDist,center = T))) %>%
    dplyr::filter(mDist_sd < 2) %>%
    dplyr::select(!c(F1_mad, F2_mad, mDist, mDist_sd)) %>%
    dplyr::mutate(F1_z = scale(F1_Hz, center = TRUE),
                  F2_z = scale(F2_Hz, center = TRUE),
                  F3_z = scale(F3_Hz, center = TRUE),
                  F1_b = emuR::bark(F1_Hz),
                  F2_b = emuR::bark(F2_Hz),
                  F3_b = emuR::bark(F3_Hz))
  
  rm(Pitch_PRAAT)
  
  
## Corner Dispersion ----
  wedge <- vowelData %>%
    dplyr::group_by(Vowel) %>%
    dplyr::summarize(mean_F1 = mean(F1_tempMid),
              mean_F2 = mean(F2_tempMid),
              mean_F1_z = mean(F1_z_tempMid),
              mean_F2_z = mean(F2_z_tempMid),
              mean_F1_b = mean(F1_b_tempMid),
              mean_F2_b = mean(F2_b_tempMid)) %>%
    dplyr::filter(Vowel == "v")
    
  corner_dis <- vowelData %>%
    dplyr::filter(Vowel != "v") %>%
    dplyr::group_by(Vowel) %>%
    dplyr::summarize(mean_F1 = mean(F1_tempMid),
              mean_F2 = mean(F2_tempMid),
              mean_F1_z = mean(F1_z_tempMid),
              mean_F2_z = mean(F2_z_tempMid),
              mean_F1_b = mean(F1_b_tempMid),
              mean_F2_b = mean(F2_b_tempMid)) %>%
    dplyr::mutate(Vowel_ED = sqrt((mean_F1-wedge$mean_F1)^2 + (mean_F2-wedge$mean_F2)^2),
                  Vowel_ED_z = sqrt((mean_F1_z-wedge$mean_F1_z)^2 + (mean_F2_z-wedge$mean_F2_z)^2),
                  Vowel_ED_b = sqrt((mean_F1_b-wedge$mean_F1_b)^2 + (mean_F2_b-wedge$mean_F2_b)^2))

    
# Plot Corner Dispersion
      # Changing to IPA symbols
      corner_dis <- corner_dis %>%
        dplyr::mutate(Vowel = dplyr::case_when(
          Vowel == "ae" ~ "æ",
          TRUE ~ Vowel
        ))
      
      wedge <- wedge %>%
        dplyr::mutate(Vowel = case_when(
          Vowel == "v" ~ "ʌ",
          TRUE ~ Vowel
        ))
      
      CDplot <- ggplot(aes(x=F2_b,
                           y=F1_b),
                       data = Formants_PRAAT,
                       inherit.aes = FALSE) + 
      geom_point(shape = 21,
                 alpha = formantAlpha,
                 color = formantColor) + 
      geom_line(aes(x = mean_F2_b,
                    y = mean_F1_b),
                data = corner_dis %>%
                  dplyr::select(Vowel:mean_F2_b) %>%
                  dplyr::filter(Vowel == "i") %>%
                  rbind(.,wedge),
                color = lineColor,
                size = 1.5,
                alpha = lineAlpha) +
      geom_line(aes(x = mean_F2_b,
                    y = mean_F1_b),
                data = corner_dis %>%
                  dplyr::select(Vowel:mean_F2_b) %>%
                  dplyr::filter(Vowel == "a") %>%
                  rbind(.,wedge),
                color = lineColor,
                size = 1.5,
                alpha = lineAlpha) +
      geom_line(aes(x = mean_F2_b,
                    y = mean_F1_b),
                data = corner_dis %>%
                  dplyr::select(Vowel:mean_F2_b) %>%
                  dplyr::filter(Vowel == "æ") %>%
                  rbind(.,wedge),
                color = lineColor,
                size = 1.5,
                alpha = lineAlpha) +
      geom_line(aes(x = mean_F2_b,
                    y = mean_F1_b),
                data = corner_dis %>%
                  dplyr::select(Vowel:mean_F2_b) %>%
                  dplyr::filter(Vowel == "u") %>%
                  rbind(.,wedge),
                color = lineColor,
                size = 1.5,
                alpha = lineAlpha) +
      geom_point(aes(x = mean_F2_b,
                     y = mean_F1_b,
                     color = Vowel),
                 data = corner_dis %>%
                  dplyr::select(Vowel:mean_F2_b) %>%
                  rbind(.,wedge),
                 inherit.aes = FALSE,
                 size = 5) +
      scale_y_reverse() +
      scale_x_reverse() +
      theme_classic() + labs(title = paste("Corner Dispersion")) + xlab("F2 (bark)") + ylab("F1 (bark)") +
      theme(plot.title = element_text(hjust = 0.5),
            aspect.ratio = 1) +
          scale_color_manual(values = c("a" = "#1AAD77",
                                        "æ" = "#1279B5",
                                        "i" = "#FFBF00",
                                        "u" = "#FD7853",
                                        "ʌ" = "#BF3178"))
    CDplot
    
      rm(corner_dis, wedge)
      
## Vowel Space Area ----
  VSA_coords <- vowelData %>%
    dplyr::filter(Vowel != "v") %>%
    dplyr::group_by(Vowel) %>%
    dplyr::summarize(mean_F1 = mean(F1_tempMid),
              mean_F2 = mean(F2_tempMid),
              mean_F1_z = mean(F1_z_tempMid),
              mean_F2_z = mean(F2_z_tempMid),
              mean_F1_b = mean(F1_b_tempMid),
              mean_F2_b = mean(F2_b_tempMid)) 
  
### Plotting VSA
    VSA_coords <- VSA_coords %>%
        dplyr::mutate(Vowel = case_when(
          Vowel == "ae" ~ "æ",
          TRUE ~ Vowel
        ))
    
    VSAplot <- ggplot(aes(x = F2_b,
                          y = F1_b),
                      data = Formants_PRAAT,
                      inherit.aes = FALSE) + 
      geom_point(shape = 21,
                 alpha = formantAlpha,
                 color = formantColor) + 
      geom_polygon(aes(x = mean_F2_b,
                       y = mean_F1_b),
                   data = VSA_coords,
                   alpha = lineAlpha,
                   color = lineColor,
                   fill=NA,
                   size = 1.5) +
      geom_point(aes(x = mean_F2_b,
                     y = mean_F1_b,
                     color = Vowel),
                 data = VSA_coords,
                 inherit.aes = FALSE,
                 size = 5) +
      scale_y_reverse() +
      scale_x_reverse() +
      guides(color = FALSE) +
      theme_classic() + labs(title = "VSA") + xlab("F2 (bark)") + ylab("F1 (bark)") +
      theme(plot.title = element_text(hjust = 0.5),
            aspect.ratio = 1) +
                scale_color_manual(values = c("a" = "#1AAD77",
                                        "æ" = "#1279B5",
                                        "i" = "#FFBF00",
                                        "u" = "#FD7853"))
    VSAplot
  
  rm(VSA_coords)
  
## Automatic VSA ----
  RefData <- openxlsx::read.xlsx("Prepped Data/Example Data/Hillenbrand Vowel Data.xlsx",
                     sheet = "Hillenbrand Vowel Data") %>%
  dplyr::rename(Speaker = 1,
                F1_Hz = 4,
                F2_Hz = 5) %>%
  dplyr::select(Speaker, F1_Hz, F2_Hz) %>%
  dplyr::filter(!grepl("b|g",Speaker)) %>%
  dplyr::mutate(F1 = emuR::bark(F1_Hz),
                F2 = emuR::bark(F2_Hz),
                Sex = ifelse(grepl("m",Speaker),"M","F"),
                Vowel = case_when(
                  grepl(pattern = "uw", Speaker) ~ "u",
                  grepl(pattern = "ah", Speaker) ~ "a",
                  grepl(pattern = "iy", Speaker) ~ "i",
                  grepl(pattern = "uh", Speaker) ~ "v",
                  grepl(pattern = "ae", Speaker) ~ "ae",
                  grepl(pattern = "aw", Speaker) ~ "ɔ",
                  grepl(pattern = "eh", Speaker) ~ "ɛ",
                  grepl(pattern = "er", Speaker) ~ "ɝ",
                  grepl(pattern = "ei", Speaker) ~ "eɪ",
                  grepl(pattern = "ih", Speaker) ~ "ɪ",
                  grepl(pattern = "oa", Speaker) ~ "o",
                  grepl(pattern = "oo", Speaker) ~ "ʊ"
                )) %>%
  dplyr::filter(!is.na(Vowel)) %>%
  dplyr::select(!Speaker) %>%
  dplyr::group_by(Sex, Vowel) %>%
  dplyr::summarise(F1_Ref = mean(F1),
                   F2_Ref = mean(F2)) %>%
    dplyr::ungroup() %>%
    dplyr::filter(Sex == "F") %>%
    dplyr::select(!c(Sex, Vowel))
  
  autoVSA <- Formants_PRAAT %>%
    dplyr::select(F1_b,F2_b) %>%
    stats::kmeans(., centers = RefData, nstart = 100, iter.max = 1000) %>%
    .$centers %>%
    as.data.frame()
  
  convexCoords <- autoVSA %>%
    as.matrix() %>%
    grDevices::chull()
  
  autoConvex <- autoVSA %>%
        slice(convexCoords)
  
### Plotting Automatic VSA
    autoVSAplot <- ggplot(aes(x = F2_b,
                          y = F1_b),
                      data = Formants_PRAAT,
                      inherit.aes = FALSE) + 
      geom_point(shape = 21,
                 alpha = formantAlpha,
                 color = formantColor) + 
      geom_polygon(aes(x = F2_b,
                       y = F1_b),
                   data = autoConvex,
                   alpha = lineAlpha,
                   color = lineColor,
                   fill=NA,
                   size = 1.5) +
      geom_point(aes(x = F2_b,
                     y = F1_b),
                 data = autoVSA,
                 inherit.aes = FALSE,
                 size = 2) +
      scale_y_reverse() +
      scale_x_reverse() +
      #guides(color = FALSE) +
      theme_classic() +
      labs(title = "Automatic VSA") +
      xlab("F2 (bark)") +
      ylab("F1 (bark)") +
      theme(plot.title = element_text(hjust = 0.5),
            aspect.ratio = 1)
    autoVSAplot
  
  rm(VSA_coords)
  
## Hull ----
### Plotting Hull
      convexCoords <- Formants_PRAAT %>%
        dplyr::select(F1_b, F2_b) %>%
        as.matrix() %>%
        grDevices::chull()
      convex <- Formants_PRAAT %>%
        slice(convexCoords)

      hullPlot <- ggplot(aes(F2_b, F1_b),
                         data = Formants_PRAAT) +
        geom_point(shape = 21,
                 alpha = formantAlpha,
                 color = formantColor) +
        geom_polygon(data = convex,
                     alpha = .5,
                     color = "#1279B5",
                     fill = NA,
                     size = 1.5) +
        scale_y_reverse() +
        scale_x_reverse() +
        theme_classic() + labs(title = "VSA Hull") + xlab("F2 (bark)") + ylab("F1 (bark)") +
      theme(plot.title = element_text(hjust = 0.5),
            aspect.ratio = 1)
      hullPlot
    
  
## Vowel Space Density ----

# Bark Normalized Density ----
# selecting the bandwidth
H_hpi <- ks::Hpi(x = Formants_PRAAT[,c("F2_b","F1_b")], pilot = "samse", pre = "scale", binned = T)

# compute 2d kde
k <- kde(x = Formants_PRAAT[,c("F2_b","F1_b")],
         H = H_hpi,
         binned = T,
         gridsize = 250)

#density <- k[["estimate"]]

# Before we can plot the density estimate we need to melt it into long format
mat.melted <- data.table::melt(k$estimate)
names(mat.melted) <- c("x", "y", "density")

# We need to add two more colums to preserve the axes units
mat.melted$F2.b <- rep(k$eval.points[[1]], times = nrow(k$estimate))
mat.melted$F1.b <- rep(k$eval.points[[2]], each = nrow(k$estimate))
mat.melted$density <- scales::rescale(mat.melted$density, to = c(0, 1))

# VSD - 25
nVSD_25 <- mat.melted %>%
  dplyr::filter(density > .25) %>%
  dplyr::select(F2.b,F1.b, density) %>%
  dplyr::rename(Density = density)

convexCoords <- nVSD_25 %>%
  dplyr::select(F2.b, F1.b) %>%
  as.matrix() %>%
  #grDevices::xy.coords() %>%
  grDevices::chull()
nconvex_25 <- nVSD_25 %>%
  slice(convexCoords)

# VSD - 75
nVSD_75 <- mat.melted %>%
  dplyr::filter(density > .75) %>%
  dplyr::select(F2.b,F1.b, density) %>%
  dplyr::rename(Density = density)

convexCoords <- nVSD_75 %>%
  dplyr::select(F2.b, F1.b) %>%
  as.matrix() %>%
  grDevices::chull()
nconvex_75 <- nVSD_75 %>%
  slice(convexCoords)

# Plotting Z Normalized VSD 
    rf <- colorRampPalette(rev(RColorBrewer::brewer.pal(11, "Spectral")))
    r <- rf(32)
    
    plotData <- mat.melted %>%
                        dplyr::rename(Density = density) %>%
                        dplyr::mutate(VSDlabel = dplyr::case_when(
                          Density < .25 ~ "none",
                          Density > .25 && Density < .75 ~ "VSD25",
                          TRUE ~ "VSD75"
                        ))
geom.text.size <- 2
    VSDplot <- ggplot(data = plotData,
                      aes(x = F2.b,
                          y = F1.b,
                          fill = Density)) + 
      geom_tile() + 
      scale_fill_viridis_c() +
      scale_x_reverse(expand = c(0, 0), 
                      breaks = round(seq(min(mat.melted$F2.b), 
                                         max(mat.melted$F2.b), by = 2))) +
      scale_y_reverse(expand = c(0, 0),
                      breaks = round(seq(min(mat.melted$F1.b),
                                         max(mat.melted$F1.b), by = 2))) + 
      ylab("F1 (bark)") + xlab("F2 (bark)") +
      labs(title = "VSD Hull") +
      theme(plot.title = element_text(hjust = 0.5),
            aspect.ratio = 1) +
      geom_polygon(data = nconvex_25, alpha = lineAlpha, color = lineColor, size = 1.5, fill = NA, linetype = 2) +
      geom_polygon(data = nconvex_75, alpha = lineAlpha, color = lineColor, size = 1.5, fill = NA, linetype = 1) +
    # VSD 25 Label
      annotate(geom = "curve",
               x = 6.9, y = 1.7+.5,
               xend = 8.5, yend = 3.5,
               curvature = -.3,
               arrow = arrow(length = unit(2, "mm")),
               color = "white") +
      annotate(geom = "text",
               x = 7.5, y = 1.7,
               label = deparse(bquote(VSD[25])),
               hjust = "center",
               color = "white",
               parse=TRUE) +
    # VSD 75 Label
      annotate(geom = "curve",
               x = 7.5, y = 7.5-.5,
               xend = 11.35, yend = 5.5,
               curvature = .3,
               arrow = arrow(length = unit(2, "mm")),
               color = "white") +
      annotate(geom = "text",
               x = 7, y = 7.5,
               label = deparse(bquote(VSD[75])),
               hjust = "center",
               color = "white",
               parse = TRUE)
     VSDplot

# Combined Plot
     
     row1 <- VSAplot + CDplot +
        patchwork::plot_layout(guides = 'collect',
                         ncol = 2) & theme(legend.position = 'right')
     row2 <- autoVSAplot + hullPlot + VSDplot +
        patchwork::plot_layout(guides = 'collect',
                         ncol = 3) & theme(legend.position = 'right')
     
     measuresPlot <- row1 / row2 + patchwork::plot_layout(heights = c(1/2, 1/2), byrow = FALSE)
     measuresPlot
     
     rm(row1, row2)

ggsave(filename = "Plots/Measures.png",
       plot = measuresPlot,
       height = 5.5,
       width = 8,
       scale = .8)

Filtering Process

formantAlpha <- .20
myPal <- c("#1279B5","#2D2D37")

Pitch_PRAAT <- list.files(path = paste("Prepped Data/Example Data/", sep = ""), 
                              pattern = ".Pitch", ignore.case = T) %>%
    paste("Prepped Data/Example Data/",., sep = "") %>%
    read.delim(., header = F) %>%
    dplyr::rename(Pitch = V1) %>%
    dplyr::mutate(Pitch = gsub("--undefined--",NA,Pitch),
                  Pitch = as.numeric(Pitch))

Formants_PRAAT <- list.files(path = paste("Prepped Data/Example Data/", sep = ""), 
                              pattern = "_Formant", ignore.case = T) %>%
    paste("Prepped Data/Example Data/",., sep = "") %>%
    read.delim(., header = T) %>%
    dplyr::select(!c(nformants, B1.Hz., B2.Hz., B3.Hz., F4.Hz., B4.Hz., F5.Hz., B5.Hz.)) %>%
    dplyr::rename(Time_s = time.s.,
                  F1_Hz = F1.Hz.,
                  F2_Hz = F2.Hz.,
                  F3_Hz = F3.Hz.) %>%
    dplyr::mutate(F1_Hz = ifelse(F1_Hz == 0, NA, F1_Hz),
                  F2_Hz = ifelse(F2_Hz == 0, NA, F2_Hz),
                  F3_Hz = ifelse(F3_Hz == 0, NA, F3_Hz)) %>%
    dplyr::mutate(F1_Hz = as.numeric(F1_Hz),
                  F2_Hz = as.numeric(F2_Hz),
                  F3_Hz = suppressWarnings(as.numeric(F3_Hz)),
                  Time_ms = Time_s / 1000,
                  F1_kHz = F1_Hz / 1000,
                  F2_kHz = F2_Hz / 1000,
                  F3_kHz = F3_Hz / 1000,
                  F1_b = emuR::bark(F1_Hz),
                  F2_b = emuR::bark(F2_Hz),
                  F3_b = emuR::bark(F3_Hz)) %>%
    dplyr::select(!Time_s) %>%
    dplyr::relocate(Time_ms, .before = F1_Hz) %>%
    cbind(.,Pitch_PRAAT)
  
  c <- 2
  while(c < NROW(Formants_PRAAT)){
    Formants_PRAAT$F1_Hz[c] <- ifelse(is.na(Formants_PRAAT$F1_Hz[c-1]) &&
                                        is.na(Formants_PRAAT$F1_Hz[c+1]),
                                      NA,
                                      Formants_PRAAT$F1_Hz[c])
    Formants_PRAAT$F2_Hz[c] <- ifelse(is.na(Formants_PRAAT$F2_Hz[c-1]) &&
                                        is.na(Formants_PRAAT$F2_Hz[c+1]),
                                      NA,
                                      Formants_PRAAT$F2_Hz[c])
    c <- c + 1
  }
  rm(c)
  
  # Raw Formants ----
  f1 <- ggplot(aes(x=F2_b,
                   y=F1_b),
               data = Formants_PRAAT) + 
      geom_point(shape = 21, color = myPal[2]) +
      scale_y_reverse() +
      scale_x_reverse() +
      scale_color_manual(values = myPal) +
      theme_classic() + labs(title = paste("Raw Formant Values")) + xlab("F2 (bark)") + ylab("F1 (bark)") +
      theme(plot.title = element_text(hjust = 0.5),
            aspect.ratio = 1,
            legend.title = element_blank(),
            legend.text = element_text(size=12))
    
# Step #1: Voiced Segments ----
    plotData <- Formants_PRAAT %>%
                   dplyr::mutate(isOutlier = case_when(
                     is.na(Pitch) ~ "Removed",
                     TRUE ~ "Retained"
                   ))
    f2 <- ggplot(data = plotData,
                 aes(x = F2_b,
                     y = F1_b,
                     color = isOutlier)) + 
      geom_point(shape = 21, data = plotData %>%
                   dplyr::filter(isOutlier == "Removed")) +
      geom_point(shape = 21, data = plotData %>%
             dplyr::filter(isOutlier == "Retained")) +
      scale_y_reverse() +
      scale_x_reverse() +
      scale_color_manual(values = myPal) +
      theme_classic() + labs(title = paste("Step #1:\nVoiced Segments")) +
      xlab("F2 (bark)") +
      ylab("F1 (bark)") +
      theme(plot.title = element_text(hjust = 0.5),
            aspect.ratio = 1,
            legend.title = element_blank(),
            legend.text = element_text(size=12))
    
# Step 2: MAD ----
    plotData <- Formants_PRAAT %>%
      dplyr::filter(!is.na(Pitch)) %>%
      dplyr::mutate(F1_mad = (abs(F1_Hz - median(F1_Hz))/ mad(F1_Hz, constant = 1.4826)) > 2.5,
                    F2_mad = (abs(F2_Hz - median(F2_Hz))/ mad(F2_Hz, constant = 1.4826)) > 2.5,
                    isOutlier = case_when(
                      F1_mad == TRUE | F2_mad == TRUE ~ "Removed",
                      TRUE ~ "Retained"
               ))
    
    f3 <- ggplot(data = plotData,
                 aes(x = F2_b,
                     y = F1_b,
                     color = isOutlier)) + 
      geom_point(shape = 21, data = plotData %>%
                   dplyr::filter(isOutlier == "Removed")) +
      geom_point(shape = 21, data = plotData %>%
             dplyr::filter(isOutlier == "Retained")) +
      scale_y_reverse() +
      scale_x_reverse() +
      scale_color_manual(values = myPal) +
      theme_classic() +
      labs(title = paste("Step #2:\nMedian Absolute Deviation")) +
      xlab("F2 (bark)") +
      ylab("F1 (bark)") +
      theme(plot.title = element_text(hjust = 0.5),
            aspect.ratio = 1,
            legend.title = element_blank(),
            legend.text = element_text(size=12))
    
# Step 3: Mahalanhobis Distance ----
  plotData <- Formants_PRAAT %>%
      dplyr::filter(!is.na(Pitch)) %>%
      dplyr::mutate(F1_mad = (abs(F1_Hz - median(F1_Hz))/ mad(F1_Hz, constant = 1.4826)) > 2.5,
                    F2_mad = (abs(F2_Hz - median(F2_Hz))/ mad(F2_Hz, constant = 1.4826)) > 2.5) %>%
      dplyr::filter(F1_mad == FALSE & F2_mad == FALSE) %>%
      dplyr::mutate(mDist = mahalanobis(cbind(.$F1_Hz, .$F2_Hz),
                                      colMeans(cbind(.$F1_Hz, .$F2_Hz)),
                                      cov = cov(cbind(.$F1_Hz, .$F2_Hz))),
                  mDist_sd = abs(scale(mDist,center = T)),
                  isOutlier = case_when(
                    mDist_sd < 2 ~ "Retained",
                    TRUE ~ "Removed"
                  ))
    
    f4 <- ggplot(data = plotData,
                 aes(x = F2_b,
                     y = F1_b,
                     color = isOutlier)) + 
      geom_point(shape = 21, data = plotData %>%
                   dplyr::filter(isOutlier == "Removed")) +
      geom_point(shape = 21, data = plotData %>%
             dplyr::filter(isOutlier == "Retained")) +
      scale_y_reverse() +
      scale_x_reverse() +
      scale_color_manual(values = myPal) +
      theme_classic() + labs(title = paste("Step #3:\nMahalanobis Distance")) + xlab("F2 (bark)") + ylab("F1 (bark)") +
      theme(plot.title = element_text(hjust = 0.5),
            aspect.ratio = 1,
            legend.title = element_blank(),
            legend.text = element_text(size=12))
    
# Final Formants ----
    plotData <- Formants_PRAAT %>%
    dplyr::filter(!is.na(Pitch)) %>%
    dplyr::mutate(F1_mad = (abs(F1_Hz - median(F1_Hz))/ mad(F1_Hz, constant = 1.4826)) > 2.5,
                  F2_mad = (abs(F2_Hz - median(F2_Hz))/ mad(F2_Hz, constant = 1.4826)) > 2.5) %>%
    dplyr::filter(F1_mad == FALSE & F2_mad == FALSE) %>%
    dplyr::mutate(mDist = mahalanobis(cbind(.$F1_Hz, .$F2_Hz),
                                      colMeans(cbind(.$F1_Hz, .$F2_Hz)),
                                      cov = cov(cbind(.$F1_Hz, .$F2_Hz))),
                  mDist_sd = abs(scale(mDist,center = T))) %>%
    dplyr::filter(mDist_sd < 2)
    
    f5 <- ggplot(aes(x=F2_b,
                     y=F1_b),
                       data = plotData,
                       inherit.aes = FALSE) + 
      geom_point(shape = 21, color = myPal[2]) + 
      scale_y_reverse() +
      scale_x_reverse() +
      theme_classic() + labs(title = paste("Final Formant Values")) + xlab("F2 (bark)") + ylab("F1 (bark)") +
      theme(plot.title = element_text(hjust = 0.5),
            aspect.ratio = 1, legend.title = element_blank())
    
# Comibing plots
    filteredPlot <- f1 + f2 + f3 + f4 + f5 + patchwork::guide_area() +
      patchwork::plot_layout(guides = 'collect',
                         ncol = 3)
    filteredPlot
    
    ggsave(plot = filteredPlot, "Plots/Filtered Formants.png",
           height = 6,
           width = 8,
           units = "in",
           scale = .9)
  

OT vs. VAS

plotData_Int <- AcousticData %>%
  dplyr::filter(!grepl("_rel", Speaker)) %>%
  dplyr::group_by(Speaker) %>%
  dplyr::mutate(segMin = base::min(VAS, transAcc),
                segMax = base::max(VAS, transAcc),
                ratingAvg = mean(VAS, transAcc, na.rm = T),
                Speaker = as.factor(Speaker),
                Etiology = as.factor(Etiology)) %>%
  arrange(segMax)

my_pal <- c("#f26430", "#272D2D","#256eff")
# With a bit more style
plot_Int <- ggplot(plotData_Int) +
  geom_segment(aes(x = fct_inorder(Speaker),
                   xend = Speaker,
                   y = segMin,
                   yend = segMax,
                   color = Etiology)) +
  geom_point(aes(x = Speaker,
                 y = VAS,
                 color = Etiology),
             #color = my_pal[1],
             size = 3,
             shape = 19) +
  geom_point(aes(x = Speaker,
                 y = transAcc,
                 color = Etiology),
             #color = my_pal[2],
             size = 3,
             shape = 15) +
  coord_flip()+
  theme_classic() +
  theme(
    legend.position = "none",
    panel.border = element_blank(),
  ) +
  xlab("") +
  ylab("Speech Intelligibility") +
  ggtitle("Speech Intelligibility") +
  ylim(c(0,100))
plot_Int

myPal <- c("#1AAD77", "#1279B5", "#FFBF00", "#FD7853", "#BF3178")
myShapes <- c(16, 18, 17, 15)

scatter1 <- ggplot(plotData_Int,
                  aes(x = VAS,
                      y = transAcc,
                      color = Etiology,
                      shape = Etiology,
                      linetype = Etiology)) +
  geom_point() +
  #geom_smooth(method = "lm", se = F) +
  geom_abline(intercept = 0, slope = 1) +
  coord_cartesian(xlim = c(0,100), ylim = c(0,100)) +
  labs(x = "Intelligibility (VAS)", y = "Intelligibility (OT)") +
  scale_color_manual(values = myPal) +
  scale_shape_manual(values = myShapes) +
  theme_classic() +
  theme(aspect.ratio=1,
        legend.position="right")

scatter2 <- ggplot(plotData_Int,
                  aes(x = VAS,
                      y = transAcc,
                      color = Etiology,
                      shape = Etiology,
                      linetype = Etiology)) +
  #geom_point() +
  geom_smooth(method = "lm", se = F) +
  geom_abline(intercept = 0, slope = 1) +
  coord_cartesian(xlim = c(0,100), ylim = c(0,100)) +
  labs(x = "Intelligibility (VAS)", y = "Intelligibility (OT)") +
  scale_color_manual(values = myPal) +
  scale_shape_manual(values = myShapes) +
  theme_classic() +
  theme(aspect.ratio=1,
        legend.position="right")

combinedScatter <- ggarrange(scatter1,
                             scatter2,
                             common.legend = F,
                             ncol = 2,
                             nrow = 1)
combinedScatter

ggsave(filename = "Plots/OT and VAS Scatterplot.png",
       plot = combinedScatter,
       height = 2,
       width = 6,
       units = "in",
       scale = 1)

rm(scatter1, scatter2, combinedScatter)

Model Scatterplots

modelFigureData <- AcousticData %>%
  dplyr::filter(!grepl("_rel",Speaker)) %>%
  dplyr::select(Speaker, Etiology, Sex, autoVSA, VSA_b, vowel_ED_b, Hull_b, Hull_bVSD_25, Hull_bVSD_75, VAS, transAcc) %>%
  dplyr::mutate(Speaker = as.factor(Speaker),
                Etiology = as.factor(Etiology),
                Sex = as.factor(Sex)) %>%
  tidyr::pivot_longer(cols = VAS:transAcc, names_to = "IntType", values_to = "Int") %>%
  dplyr::mutate(IntType = case_when(
    IntType == "transAcc" ~ "OT",
    TRUE ~ "VAS"
  ),
                IntType = as.factor(IntType))

ylabel <- "Intelligibility"
myPal <- c("#2D2D37", "#1279B5")
myPalShape <- c(19, 1)

VSA <- modelFigureData %>%
  ggplot() +
  aes(x = VSA_b,
      y = Int,
      color = IntType,
      shape = IntType,
      linetype = IntType) +
  geom_point() +
  geom_smooth(method = "lm", se = T, fill = "light grey") +
  xlab(expression("VSA (Bark"^2*")")) +
  ylab(ylabel) +
  coord_cartesian(ylim = c(0,100)) +
  theme_classic() +
  theme(plot.title = element_text(hjust = 0.5, face = "bold"),
        aspect.ratio=1) +
  scale_color_manual(values = myPal) +
  scale_shape_manual(values = myPalShape) +
  labs(color="Intelligibility Type",
       shape = "Intelligibility Type",
       linetype = "Intelligibility Type")

autoVSA <- modelFigureData %>%
  ggplot() +
  aes(x = autoVSA,
      y = Int,
      color = IntType,
      shape = IntType,
      linetype = IntType) +
  geom_point() +
  geom_smooth(method = "lm", se = T, fill = "light grey") +
  xlab(expression("VSA"[Automatic]*" (Bark"^2*")")) +
  ylab(ylabel) +
  coord_cartesian(ylim = c(0,100)) +
  theme_classic() +
  theme(plot.title = element_text(hjust = 0.5, face = "bold"),
        aspect.ratio=1) +
  scale_color_manual(values = myPal) +
  scale_shape_manual(values = myPalShape) +
  labs(color="Intelligibility Type",
       shape = "Intelligibility Type",
       linetype = "Intelligibility Type")

disp <- modelFigureData %>%
  ggplot() +
  aes(x = vowel_ED_b,
      y = Int,
      color = IntType,
      shape = IntType,
      linetype = IntType) +
  geom_point() +
  geom_smooth(method = "lm", se = T, fill = "light grey") +
  xlab("Corner Dispersion (Bark)") +
  ylab(ylabel) +
  coord_cartesian(ylim = c(0,100)) +
  theme_classic() +
  theme(aspect.ratio=1) +
  scale_color_manual(values = myPal) +
  scale_shape_manual(values = myPalShape) +
  labs(color="Intelligibility Type",
       shape = "Intelligibility Type",
       linetype = "Intelligibility Type")

Hull <- modelFigureData %>%
  ggplot() +
  aes(x = Hull_b,
      y = Int,
      color = IntType,
      shape = IntType,
      linetype = IntType) +
  geom_point() +
  geom_smooth(method = "lm", se = T, fill = "light grey") +
  xlab(expression("VSA"[Hull]*" (Bark"^2*")")) +
  ylab(ylabel) +
  coord_cartesian(ylim = c(0,100)) +
  theme_classic() +
  theme(aspect.ratio=1) + theme(legend.position = "none") +
  scale_color_manual(values = myPal) +
  scale_shape_manual(values = myPalShape) +
  labs(color="Intelligibility Type",
       shape = "Intelligibility Type",
       linetype = "Intelligibility Type")

vsd25 <- modelFigureData %>%
  ggplot() +
  aes(x = Hull_bVSD_25,
      y = Int,
      color = IntType,
      shape = IntType,
      linetype = IntType) +
  geom_point() +
  geom_smooth(method = "lm", se = T, fill = "light grey") +
  xlab(expression("VSD"[25]*" (Bark"^2*")")) +
  ylab(ylabel) +
  coord_cartesian(ylim = c(0,100)) +
  theme_classic() +
  theme(aspect.ratio=1) + theme(legend.position = "none") +
  scale_color_manual(values = myPal) +
  scale_shape_manual(values = myPalShape) +
  labs(color="Intelligibility Type",
       shape = "Intelligibility Type",
       linetype = "Intelligibility Type")

vsd75 <- modelFigureData %>%
  ggplot() +
  aes(x = Hull_bVSD_75,
      y = Int,
      color = IntType,
      shape = IntType,
      linetype = IntType) +
  geom_point() +
  geom_smooth(method = "lm", se = T, fill = "light grey") +
  xlab(expression("VSD"[75]*" (Bark"^2*")")) +
  ylab(ylabel) +
  coord_cartesian(ylim = c(0,100)) +
  theme_classic() +
  theme(aspect.ratio=1) + theme(legend.position = "none") +
  scale_color_manual(values = myPal) +
  scale_shape_manual(values = myPalShape) +
  labs(color="Intelligibility Type",
       shape = "Intelligibility Type",
       linetype = "Intelligibility Type")

# Creating OT Scatterplot Figure

scatter <- VSA  + disp + autoVSA + Hull + vsd25 + vsd75 +
  patchwork::plot_layout(guides = 'collect',
                         ncol = 3) & theme(legend.position = "bottom")
scatter 

ggsave("Plots/ModelFigure.png", scatter,
       height = 4.5,
       width = 6,
       units = "in",
       scale = 1.1)

Filtering at Different Levels

    Hull_b <- cHull(Formants_PRAAT$F1_b, Formants_PRAAT$F2_b)
Error in Polygon(chull.coords, hole = F) : 
  could not find function "Polygon"

Listener Demographic Information


ListenerDemo <- Listeners %>%
  furniture::table1(age, gender, race, ethnicity)

ListenerDemo

Speaker Demographics


SpeakerDemo <- AcousticData %>%
  dplyr::select(c(Speaker, Sex, Etiology))

Ages <- rio::import("Prepped Data/Speaker Ages.xlsx")

SpeakerDemo <- full_join(SpeakerDemo, Ages, by = "Speaker")

SpeakerDemoInfo <- SpeakerDemo %>%
  furniture::table1(Sex, Etiology, Age, na.rm = F)

SpeakerDemoInfo

SpeakerDemo %>%
  dplyr::summarize(mean_age = mean(Age, na.rm = T), age_sd = sd(Age, na.rm = T), age_range = range(Age, na.rm = T))
LS0tCnRpdGxlOiAiVm93ZWwgQWNvdXN0aWNzIGFzIFByZWRpY3RvcnMgb2YgU3BlZWNoIEludGVsbGlnaWJpbGl0eSBpbiBEeXNhcnRocmlhIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpUaGlzIGlzIHRoZSBjb2RlIGZvciB0aGUgc3RhdGlzdGljYWwgYW5hbHlzaXMgZm9yICJWb3dlbCBBY291c3RpY3MgYXMgUHJlZGljdG9ycyBvZiBTcGVlY2ggSW50ZWxsaWdpYmlsaXR5IGluIER5c2FydGhyaWEuIgoKIyBMb2FkaW5nIFBhY2thZ2VzCgpgYGB7cn0KCmxpYnJhcnkocmlvKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShpcnIpICMgaW5zdGFsbC5wYWNrYWdlcygnaXJyJykKbGlicmFyeShwZXJmb3JtYW5jZSkKbGlicmFyeShjYXIpCmxpYnJhcnkoZ2dwdWJyKQpsaWJyYXJ5KCJIbWlzYyIpICMgaW5zdGFsbC5wYWNrYWdlcygnSG1pc2MnKQpsaWJyYXJ5KGdncmlkZ2VzKQpsaWJyYXJ5KGZ1cm5pdHVyZSkgIyBpbnN0YWxsLnBhY2thZ2VzKCdmdXJuaXR1cmUnKQpsaWJyYXJ5KGd0KQpsaWJyYXJ5KHBhdGNod29yaykKbGlicmFyeShrcykKbGlicmFyeShlbXVSKSAjIGluc3RhbGwucGFja2FnZXMoJ2VtdVInKQoKYGBgCgojIFVwbG9hZCBEYXRhc2V0cwoKYGBge3J9CgpSZWxpYWJpbGl0eSA8LSByaW86OmltcG9ydCgiUHJlcHBlZCBEYXRhL1JlbGlhYmlsaXR5IERhdGEuY3N2IikKQWNvdXN0aWNEYXRhIDwtIHJpbzo6aW1wb3J0KCJQcmVwcGVkIERhdGEvQWNvdXN0aWNNZWFzdXJlcy5jc3YiKSAlPiUKICBkcGx5cjo6bXV0YXRlKGludERpZmYgPSBWQVMgLSB0cmFuc0FjYykKCkFjb3VzdGljRGF0YSA8LSBBY291c3RpY0RhdGEgJT4lCiAgZHBseXI6OmZpbHRlcighZ3JlcGwoIl9yZWwiLCBTcGVha2VyKSkgJT4lCiAgZHBseXI6OnNlbGVjdChjKFNwZWFrZXIsIFNleCwgRXRpb2xvZ3ksIHZvd2VsX0VEX2IsIFZTQV9iLCBhdXRvVlNBLAogICAgICAgICAgICAgICAgICBIdWxsX2IsSHVsbF9iVlNEXzI1LCBIdWxsX2JWU0RfNTAsIEh1bGxfYlZTRF83NSwKICAgICAgICAgICAgICAgICAgVkFTLCB0cmFuc0FjYykpICU+JQogIGRwbHlyOjptdXRhdGUoRXRpb2xvZ3kgPSBhcy5mYWN0b3IoRXRpb2xvZ3kpLAogICAgICAgICAgICAgICAgU2V4ID0gYXMuZmFjdG9yKFNleCksCiAgICAgICAgICAgICAgICBTcGVha2VyID0gYXMuZmFjdG9yKFNwZWFrZXIpKQoKTGlzdGVuZXJzIDwtIHJpbzo6aW1wb3J0KCJQcmVwcGVkIERhdGEvTGlzdGVuZXJfRGVtb2dyYXBoaWNzLmNzdiIpICU+JQogIGRwbHlyOjpzZWxlY3QoIWMoU3RhcnREYXRlOnByb2xvZmljSUQsIFEyLjRfNl9URVhULCBRMy4yXzhfVEVYVCwgQXVkaW9DaGVjazpFUDMpKQoKTGlzdGVuZXJzJHJhY2VbTGlzdGVuZXJzJFEzLjNfN19URVhUID09ICJOYXRpdmUgQW1lcmljYW4vIEFmcmljYW4gYW1lcmNpbmciXSA8LSAiQmlyYWNpYWwgb3IgTXVsdGlyYWNpYWwiCmBgYAoKCiMgSW50ZXItcmF0ZXIgUmVsaWFiaWxpdHkKClR3byByYXRlcnMgKHRoZSBmaXJzdCB0d28gYXV0aG9ycykgY29tcGxldGVkIHZvd2VsIHNlZ21lbnRhdGlvbiBmb3IgdGhlIHNwZWFrZXJzLiBUbyBjYWxjdWxhdGUgaW50ZXItcmF0ZXIgcmVsaWFiaWxpdHksIDIwJSBvZiB0aGUgc3BlYWtlcnMgd2VyZSBzZWdtZW50ZWQgYWdhaW4gYnkgdGhlIG90aGVyIHJhdGVyLiBUd28td2F5IGludHJhY2xhc3MgY29lZmZpY2llbnRzIHdlcmUgY29tcHV0ZWQgZm9yIHRoZSBleHRyYWN0ZWQgRjEgYW5kIEYyIGZyb20gdGhlIHRlbXBvcmFsIG1pZHBvaW50IG9mIHRoZSB2b3dlbCBzZWdtZW50cy4gU2luY2Ugb25seSBvbmUgc2V0IG9mIHJhdGluZ3Mgd2lsbCBiZSB1c2VkIGluIHRoZSBkYXRhIGFuYWx5c2lzLCB3ZSBmb2N1cyBvbiB0aGUgc2luZ2xlIElDQyByZXN1bHRzIGFuZCBpbnRlcnByZXRhdGlvbi4gSG93ZXZlciwgd2UgYWxzbyByZXBvcnQgdGhlIGF2ZXJhZ2UgSUNDIHZhbHVlcyB0byBiZSBjb21wcmVoZW5zaXZlLgoKYGBge3J9CgojIyBDcmVhdGluZyBuZXcgZGF0YSBmcmFtZXMgdG8gY2FsY3VsYXRlIElDQyBmb3IgZXh0cmFjdGVkIEYxIGFuZCBGMiB2YWx1ZXMKCkYxX1JlbCA8LSBSZWxpYWJpbGl0eSAlPiUKICBkcGx5cjo6c2VsZWN0KGMoRjEsIEYxX3JlbCkpCgpGMl9SZWwgPC0gUmVsaWFiaWxpdHkgJT4lCiAgZHBseXI6OnNlbGVjdChjKEYyLCBGMl9yZWwpKQogIAojIyBTaW5nbGUgSUNDIGZvciBGMQpTaW5nbGVfRjEgPC0gaXJyOjppY2MoRjFfUmVsLCBtb2RlbCA9ICJ0d293YXkiLCB0eXBlID0gImFncmVlbWVudCIsIHVuaXQgPSAic2luZ2xlIikKCiMjIEF2ZXJhZ2UgSUNDIGZvciBGMQpBdmVyYWdlX0YxIDwtIGlycjo6aWNjKEYxX1JlbCwgbW9kZWwgPSAidHdvd2F5IiwgdHlwZSA9ICJhZ3JlZW1lbnQiLCB1bml0ID0gImF2ZXJhZ2UiKQoKIyMgU2luZ2xlIElDQyBmb3IgRjIKU2luZ2xlX0YyIDwtIGlycjo6aWNjKEYyX1JlbCwgbW9kZWwgPSAidHdvd2F5IiwgdHlwZSA9ICJhZ3JlZW1lbnQiLCB1bml0ID0gInNpbmdsZSIpCgojIyBBdmVyYWdlIElDQyBmb3IgRjIKQXZlcmFnZV9GMiA8LSBpcnI6OmljYyhGMl9SZWwsIG1vZGVsID0gInR3b3dheSIsIHR5cGUgPSAiYWdyZWVtZW50IiwgdW5pdCA9ICJhdmVyYWdlIikKCiMjIEludGVyLXJhdGVyIHJlbGlhYmlsaXR5IHJlc3VsdHMgYW5kIGludGVycHJldGF0aW9uCgpwcmludChwYXN0ZSgiU2luZ2xlIElDQyBmb3IgRjEgaXMgIiwgcm91bmQoU2luZ2xlX0YxJHZhbHVlLCBkaWdpdHMgPSAzKSwgIi4gIiwgCiAgICAgICAgICAgICJUaGUgOTUlIENJIGlzIFsiLCByb3VuZChTaW5nbGVfRjEkbGJvdW5kLCBkaWdpdHMgPSAzKSwgIiAtICIsIHJvdW5kKFNpbmdsZV9GMSR1Ym91bmQsIGRpZ2l0cyA9IDMpLCAiXS4iLCBzZXAgPSAiIikpCgpwcmludChwYXN0ZSgiU2luZ2xlIElDQyBmb3IgRjIgaXMgIiwgcm91bmQoU2luZ2xlX0YyJHZhbHVlLCBkaWdpdHMgPSAzKSwgIi4gIiwgCiAgICAgICAgICAgICJUaGUgOTUlIENJIGlzIFsiLCByb3VuZChTaW5nbGVfRjIkbGJvdW5kLCBkaWdpdHMgPSAzKSwgIiAtICIsIHJvdW5kKFNpbmdsZV9GMiR1Ym91bmQsIGRpZ2l0cyA9IDMpLCAiXS4iLCBzZXAgPSAiIikpCgpwcmludChwYXN0ZSgiQXZlcmFnZSBJQ0MgZm9yIEYxIGlzICIsIHJvdW5kKEF2ZXJhZ2VfRjEkdmFsdWUsIGRpZ2l0cyA9IDMpLCAiLiAiLCAKICAgICAgICAgICAgIlRoZSA5NSUgQ0kgaXMgWyIsIHJvdW5kKEF2ZXJhZ2VfRjEkbGJvdW5kLCBkaWdpdHMgPSAzKSwgIiAtICIsIHJvdW5kKEF2ZXJhZ2VfRjEkdWJvdW5kLCBkaWdpdHMgPSAzKSwgIl0uIiwgc2VwID0gIiIpKQoKcHJpbnQocGFzdGUoIkF2ZXJhZ2UgSUNDIGZvciBGMiBpcyAiLCByb3VuZChBdmVyYWdlX0YyJHZhbHVlLCBkaWdpdHMgPSAzKSwgIi4gIiwgCiAgICAgICAgICAgICJUaGUgOTUlIENJIGlzIFsiLCByb3VuZChBdmVyYWdlX0YyJGxib3VuZCwgZGlnaXRzID0gMyksICIgLSAiLCByb3VuZChBdmVyYWdlX0YyJHVib3VuZCwgZGlnaXRzID0gMyksICJdLiIsIHNlcCA9ICIiKSkKCnByaW50KCJUaHVzLCBpbnRlcnJhdGVyIHJlbGlhYmlsaXR5IGZvciB0aGUgZXh0cmFjdGVkIEYxIGFuZCBGMiB2YWx1ZXMgZnJvbSB0aGUgdm93ZWwgc2VnbWVudHMgd2FzIGdvb2QgdG8gZXhjZWxsZW50LiIpCgojIyBSZW1vdmluZyBleHRyYSBkYXRhIGZyYW1lcyBmcm9tIGVudmlyb25tZW50CgpybShGMV9SZWwsIEYyX1JlbCwgUmVsaWFiaWxpdHksIFNpbmdsZV9GMSwgU2luZ2xlX0YyLCBBdmVyYWdlX0YxLCBBdmVyYWdlX0YyKQoKYGBgCgoKIyBEZXNjcmlwdGl2ZSBTdGF0aXN0aWNzCgojIyBDb3JyZWxhdGlvbnMKCmBgYHtyfQpDb3JyTWF0cml4IDwtIEFjb3VzdGljRGF0YSAlPiUKICBkcGx5cjo6c2VsZWN0KFZTQV9iLCB2b3dlbF9FRF9iLCBhdXRvVlNBLCBIdWxsX2IsIEh1bGxfYlZTRF8yNSwgSHVsbF9iVlNEXzc1LCBWQVMsIHRyYW5zQWNjKSAlPiUKICBhcy5tYXRyaXgoKSAlPiUKICBIbWlzYzo6cmNvcnIoKQoKQ29yck1hdHJpeFAgPC0gQ29yck1hdHJpeCRQIDwgLjA1CgpDb3JyTWF0cml4IDwtIENvcnJNYXRyaXgkcgoKc3RhdHM6OmNvci50ZXN0KEFjb3VzdGljRGF0YSRWU0FfYiwgQWNvdXN0aWNEYXRhJHZvd2VsX0VEX2IsIG1ldGhvZCA9ICJwZWFyc29uIikKc3RhdHM6OmNvci50ZXN0KEFjb3VzdGljRGF0YSRIdWxsX2IsIEFjb3VzdGljRGF0YSRIdWxsX2JWU0RfMjUsIG1ldGhvZCA9ICJwZWFyc29uIikKc3RhdHM6OmNvci50ZXN0KEFjb3VzdGljRGF0YSRIdWxsX2IsIEFjb3VzdGljRGF0YSRhdXRvVlNBLCBtZXRob2QgPSAicGVhcnNvbiIpCgoKd3JpdGUuY3N2KENvcnJNYXRyaXgsIGZpbGUgPSAiVGFibGVzL0NvcnJlbGF0aW9uIE1hdHJpeC5jc3YiKQpybShDb3JyTWF0cml4KQoKYGBgCgojIFJlc2VhcmNoIFExOiBNb2RlbGluZyBJbnRlbGxpZ2liaWxpdHkKCiMjIE9ydGhvZ3JhcGhpYyBUcmFuc2NyaXB0aW9ucwpNb2RlbCAxCmBgYHtyfQoKIyBTcGVjaWZ5aW5nIE1vZGVsIDEKCk9UX01vZGVsMSA8LSBsbSh0cmFuc0FjYyB+IEh1bGxfYlZTRF8yNSwgZGF0YSA9IEFjb3VzdGljRGF0YSkKCiMjIE1vZGVsIDEgQXNzdW1wdGlvbnMgCgpwZXJmb3JtYW5jZTo6Y2hlY2tfbW9kZWwoT1RfTW9kZWwxKQoKIyMgTW9kZWwgMSBTdW1tYXJ5CgpzdW1tYXJ5KE9UX01vZGVsMSkKCmBgYAoKTW9kZWwgMgpgYGB7cn0KCiMjIFNwZWNpZnlpbmcgTW9kZWwgMgoKT1RfTW9kZWwyIDwtIGxtKHRyYW5zQWNjIH4gSHVsbF9iVlNEXzI1ICsgSHVsbF9iVlNEXzc1LCBkYXRhID0gQWNvdXN0aWNEYXRhKQoKIyMgTW9kZWwgMiBBc3N1bXB0aW9uIENoZWNrCgpwZXJmb3JtYW5jZTo6Y2hlY2tfbW9kZWwoT1RfTW9kZWwyKQoKIyMgTW9kZWwgMiBTdW1tYXJ5CgpzdW1tYXJ5KE9UX01vZGVsMikKCiMjIE1vZGVsIDEgYW5kIE1vZGVsIDIgQ29tcGFyaXNvbgoKYW5vdmEoT1RfTW9kZWwxLCBPVF9Nb2RlbDIpCgpgYGAKCk1vZGVsIDNhCmBgYHtyfQoKIyMgU3BlY2lmeWluZyBNb2RlbCAzCgpPVF9Nb2RlbDNhIDwtIGxtKHRyYW5zQWNjIH4gSHVsbF9iVlNEXzI1ICsgSHVsbF9iVlNEXzc1ICsgSHVsbF9iLCBkYXRhID0gQWNvdXN0aWNEYXRhKQoKIyMgTW9kZWwgMyBBc3N1bXB0aW9uIENoZWNrCgpwZXJmb3JtYW5jZTo6Y2hlY2tfbW9kZWwoT1RfTW9kZWwzYSkKcGVyZm9ybWFuY2U6OmNoZWNrX2NvbGxpbmVhcml0eShPVF9Nb2RlbDNhKQoKCiMjIE1vZGVsIDMgU3VtbWFyeQoKc3VtbWFyeShPVF9Nb2RlbDNhKQoKIyMgTW9kZWwgMiBhbmQgTW9kZWwgMyBDb21wYXJpc29uCgphbm92YShPVF9Nb2RlbDIsIE9UX01vZGVsM2EpCgpgYGAKCk1vZGVsIDNiCmBgYHtyfQoKIyMgU3BlY2lmeWluZyBNb2RlbCAzCgpPVF9Nb2RlbDNiIDwtIGxtKHRyYW5zQWNjIH4gSHVsbF9iVlNEXzc1ICsgSHVsbF9iLCBkYXRhID0gQWNvdXN0aWNEYXRhKQoKIyMgTW9kZWwgMyBBc3N1bXB0aW9uIENoZWNrCgpwZXJmb3JtYW5jZTo6Y2hlY2tfbW9kZWwoT1RfTW9kZWwzYikKcGVyZm9ybWFuY2U6OmNoZWNrX2NvbGxpbmVhcml0eShPVF9Nb2RlbDNiKQoKCiMjIE1vZGVsIDMgU3VtbWFyeQoKc3VtbWFyeShPVF9Nb2RlbDNiKQoKYGBgCgpNb2RlbCA0YQpgYGB7cn0KCiMjIFNwZWNpZnlpbmcgTW9kZWwgNAoKT1RfTW9kZWw0YSA8LSBsbSh0cmFuc0FjYyB+IEh1bGxfYlZTRF83NSArIEh1bGxfYiArIGF1dG9WU0EsIGRhdGEgPSBBY291c3RpY0RhdGEpCgojIyBNb2RlbCA0IEFzc3VtcHRpb24gQ2hlY2sKCnBlcmZvcm1hbmNlOjpjaGVja19tb2RlbChPVF9Nb2RlbDRhKQpwZXJmb3JtYW5jZTo6Y2hlY2tfY29sbGluZWFyaXR5KE9UX01vZGVsNGEpCgojIyBNb2RlbCA0IFN1bW1hcnkKCnN1bW1hcnkoT1RfTW9kZWw0YSkKCiMjIE1vZGVsIDMgYW5kIE1vZGVsIDQgQ29tcGFyaXNvbgoKYW5vdmEoT1RfTW9kZWwzYiwgT1RfTW9kZWw0YSkKCmBgYAoKTW9kZWwgNGIKYGBge3J9CgojIyBTcGVjaWZ5aW5nIE1vZGVsIDQKCk9UX01vZGVsNGIgPC0gbG0odHJhbnNBY2MgfiBIdWxsX2JWU0RfNzUgKyBhdXRvVlNBLCBkYXRhID0gQWNvdXN0aWNEYXRhKQoKIyMgTW9kZWwgNCBBc3N1bXB0aW9uIENoZWNrCgpwZXJmb3JtYW5jZTo6Y2hlY2tfbW9kZWwoT1RfTW9kZWw0YikKcGVyZm9ybWFuY2U6OmNoZWNrX2NvbGxpbmVhcml0eShPVF9Nb2RlbDRiKQoKIyMgTW9kZWwgNCBTdW1tYXJ5CgpzdW1tYXJ5KE9UX01vZGVsNGIpCgpgYGAKCk1vZGVsIDUKYGBge3J9CgojIyBTcGVjaWZ5aW5nIE1vZGVsIDUKCk9UX01vZGVsNSA8LSBsbSh0cmFuc0FjYyB+IEh1bGxfYlZTRF83NSArIGF1dG9WU0EgKyBWU0FfYiwgZGF0YSA9IEFjb3VzdGljRGF0YSkKCiMjIE1vZGVsIDQgQXNzdW1wdGlvbiBDaGVjawoKcGVyZm9ybWFuY2U6OmNoZWNrX21vZGVsKE9UX01vZGVsNSkKcGVyZm9ybWFuY2U6OmNoZWNrX2NvbGxpbmVhcml0eShPVF9Nb2RlbDUpCgojIyBNb2RlbCA0IFN1bW1hcnkKCnN1bW1hcnkoT1RfTW9kZWw1KQoKIyMgTW9kZWwgMyBhbmQgTW9kZWwgNCBDb21wYXJpc29uCgphbm92YShPVF9Nb2RlbDRiLCBPVF9Nb2RlbDUpCgpgYGAKCk1vZGVsIDYKYGBge3J9CgojIyBTcGVjaWZ5aW5nIE1vZGVsIDYKCk9UX01vZGVsNiA8LSBsbSh0cmFuc0FjYyB+IEh1bGxfYlZTRF83NSArIGF1dG9WU0EgKyBWU0FfYiArIHZvd2VsX0VEX2IsIGRhdGEgPSBBY291c3RpY0RhdGEpCgojIyBNb2RlbCA2IEFzc3VtcHRpb24gQ2hlY2sKCnBlcmZvcm1hbmNlOjpjaGVja19tb2RlbChPVF9Nb2RlbDYpCnBlcmZvcm1hbmNlOjpjaGVja19jb2xsaW5lYXJpdHkoT1RfTW9kZWw2KQoKIyMgTW9kZWwgNiBTdW1tYXJ5CgpzdW1tYXJ5KE9UX01vZGVsNikKCiMjIE1vZGVsIDUgYW5kIE1vZGVsIDYgQ29tcGFyaXNvbgoKYW5vdmEoT1RfTW9kZWw1LCBPVF9Nb2RlbDYpCgpgYGAKCgojIyMgRmluYWwgTW9kZWwKCmBgYHtyfQoKIyMgU3BlY2lmeWluZyBGaW5hbCBNb2RlbAoKT1RfTW9kZWxfZmluYWwgPC0gbG0odHJhbnNBY2MgfiBWU0FfYiwgZGF0YSA9IEFjb3VzdGljRGF0YSkKCiMjIEZpbmFsIE1vZGVsIEFzc3VtcHRpb24gQ2hlY2sKCnBlcmZvcm1hbmNlOjpjaGVja19tb2RlbChPVF9Nb2RlbF9maW5hbCkKCiMjIEZpbmFsIE1vZGVsIFN1bW1hcnkKCnN1bW1hcnkoT1RfTW9kZWxfZmluYWwpCmNvbmZpbnQoT1RfTW9kZWxfZmluYWwpCgpgYGAKCiMjIFZBUyBNb2RlbHMKCk1vZGVsIDEKYGBge3J9CgojIFNwZWNpZnlpbmcgTW9kZWwgMQoKVkFTX01vZGVsMSA8LSBsbShWQVMgfiBIdWxsX2JWU0RfMjUsIGRhdGEgPSBBY291c3RpY0RhdGEpCgojIyBNb2RlbCAxIEFzc3VtcHRpb25zIAoKcGVyZm9ybWFuY2U6OmNoZWNrX21vZGVsKFZBU19Nb2RlbDEpCgojIyBNb2RlbCAxIFN1bW1hcnkKCnN1bW1hcnkoVkFTX01vZGVsMSkKCmBgYAoKTW9kZWwgMgpgYGB7cn0KCiMjIFNwZWNpZnlpbmcgTW9kZWwgMgoKVkFTX01vZGVsMiA8LSBsbShWQVMgfiBIdWxsX2JWU0RfMjUgKyBIdWxsX2JWU0RfNzUsIGRhdGEgPSBBY291c3RpY0RhdGEpCgojIyBNb2RlbCAyIEFzc3VtcHRpb24gQ2hlY2sKCnBlcmZvcm1hbmNlOjpjaGVja19tb2RlbChWQVNfTW9kZWwyKQoKIyMgTW9kZWwgMiBTdW1tYXJ5CgpzdW1tYXJ5KFZBU19Nb2RlbDIpCgojIyBNb2RlbCAxIGFuZCBNb2RlbCAyIENvbXBhcmlzb24KCmFub3ZhKFZBU19Nb2RlbDEsIFZBU19Nb2RlbDIpCgpgYGAKCk1vZGVsIDNhCmBgYHtyfQoKIyMgU3BlY2lmeWluZyBNb2RlbCAzCgpWQVNfTW9kZWwzYSA8LSBsbShWQVMgfiBIdWxsX2JWU0RfMjUgKyBIdWxsX2JWU0RfNzUgKyBIdWxsX2IsIGRhdGEgPSBBY291c3RpY0RhdGEpCgojIyBNb2RlbCAzIEFzc3VtcHRpb24gQ2hlY2sKCnBlcmZvcm1hbmNlOjpjaGVja19tb2RlbChWQVNfTW9kZWwzYSkKcGVyZm9ybWFuY2U6OmNoZWNrX2NvbGxpbmVhcml0eShWQVNfTW9kZWwzYSkKCiMjIE1vZGVsIDMgU3VtbWFyeQoKc3VtbWFyeShWQVNfTW9kZWwzYSkKCiMjIE1vZGVsIDIgYW5kIE1vZGVsIDMgQ29tcGFyaXNvbgoKYW5vdmEoVkFTX01vZGVsMiwgVkFTX01vZGVsM2EpCgpgYGAKCk1vZGVsIDNiCmBgYHtyfQoKIyMgU3BlY2lmeWluZyBNb2RlbCAzYgoKVkFTX01vZGVsM2IgPC0gbG0oVkFTIH4gIEh1bGxfYlZTRF83NSArIEh1bGxfYiwgZGF0YSA9IEFjb3VzdGljRGF0YSkKCiMjIE1vZGVsIDMgQXNzdW1wdGlvbiBDaGVjawoKcGVyZm9ybWFuY2U6OmNoZWNrX21vZGVsKFZBU19Nb2RlbDNiKQpwZXJmb3JtYW5jZTo6Y2hlY2tfY29sbGluZWFyaXR5KFZBU19Nb2RlbDNiKQoKIyMgTW9kZWwgMyBTdW1tYXJ5CgpzdW1tYXJ5KFZBU19Nb2RlbDNiKQoKYGBgCk1vZGVsIDRhCmBgYHtyfQoKIyMgU3BlY2lmeWluZyBNb2RlbCA0CgpWQVNfTW9kZWw0YSA8LSBsbShWQVMgfiBIdWxsX2JWU0RfNzUgKyBhdXRvVlNBICsgSHVsbF9iLCBkYXRhID0gQWNvdXN0aWNEYXRhKQoKIyMgTW9kZWwgNCBBc3N1bXB0aW9uIENoZWNrCgpwZXJmb3JtYW5jZTo6Y2hlY2tfbW9kZWwoVkFTX01vZGVsNGEpCnBlcmZvcm1hbmNlOjpjaGVja19jb2xsaW5lYXJpdHkoVkFTX01vZGVsNGEpCgojIyBNb2RlbCA0IFN1bW1hcnkKCnN1bW1hcnkoVkFTX01vZGVsNGEpCgojIyBNb2RlbCAzIGFuZCBNb2RlbCA0IENvbXBhcmlzb24KCmFub3ZhKFZBU19Nb2RlbDNiLCBWQVNfTW9kZWw0YSkKCmBgYAoKTW9kZWwgNGIKYGBge3J9CgojIyBTcGVjaWZ5aW5nIE1vZGVsIDQKClZBU19Nb2RlbDRiIDwtIGxtKFZBUyB+IEh1bGxfYlZTRF83NSArIGF1dG9WU0EsIGRhdGEgPSBBY291c3RpY0RhdGEpCgojIyBNb2RlbCA0IEFzc3VtcHRpb24gQ2hlY2sKCnBlcmZvcm1hbmNlOjpjaGVja19tb2RlbChWQVNfTW9kZWw0YikKcGVyZm9ybWFuY2U6OmNoZWNrX2NvbGxpbmVhcml0eShWQVNfTW9kZWw0YikKCiMjIE1vZGVsIDQgU3VtbWFyeQoKc3VtbWFyeShWQVNfTW9kZWw0YikKCmBgYApNb2RlbCA1CmBgYHtyfQoKIyMgU3BlY2lmeWluZyBNb2RlbCA1CgpWQVNfTW9kZWw1IDwtIGxtKFZBUyB+IEh1bGxfYlZTRF83NSArIGF1dG9WU0EgKyBWU0FfYiwgZGF0YSA9IEFjb3VzdGljRGF0YSkKCiMjIE1vZGVsIDUgQXNzdW1wdGlvbiBDaGVjawoKcGVyZm9ybWFuY2U6OmNoZWNrX21vZGVsKFZBU19Nb2RlbDUpCgojIyBNb2RlbCA1IFN1bW1hcnkKCnN1bW1hcnkoVkFTX01vZGVsNSkKCiMjIE1vZGVsIDQgYW5kIE1vZGVsIDUgQ29tcGFyaXNvbgoKYW5vdmEoVkFTX01vZGVsNGIsIFZBU19Nb2RlbDUpCgpgYGAKCk1vZGVsIDYKYGBge3J9CgojIyBTcGVjaWZ5aW5nIE1vZGVsIDYKClZBU19Nb2RlbDYgPC0gbG0oVkFTIH4gSHVsbF9iVlNEXzc1ICsgYXV0b1ZTQSArIFZTQV9iICsgdm93ZWxfRURfYiwgZGF0YSA9IEFjb3VzdGljRGF0YSkKCiMjIE1vZGVsIDYgQXNzdW1wdGlvbiBDaGVjawoKcGVyZm9ybWFuY2U6OmNoZWNrX21vZGVsKFZBU19Nb2RlbDYpCgojIyBNb2RlbCA2IFN1bW1hcnkKCnN1bW1hcnkoVkFTX01vZGVsNikKCiMjIE1vZGVsIDUgYW5kIE1vZGVsIDYgQ29tcGFyaXNvbgoKYW5vdmEoVkFTX01vZGVsNSwgVkFTX01vZGVsNikKCmBgYAoKIyMjIEZpbmFsIE1vZGVsCgpgYGB7cn0KCiMjIFNwZWNpZnlpbmcgRmluYWwgTW9kZWwKClZBU19Nb2RlbF9maW5hbCA8LSBsbShWQVMgfiBWU0FfYiwgZGF0YSA9IEFjb3VzdGljRGF0YSkKCiMjIEZpbmFsIE1vZGVsIEFzc3VtcHRpb24gQ2hlY2sKCnBlcmZvcm1hbmNlOjpjaGVja19tb2RlbChWQVNfTW9kZWxfZmluYWwpCgojIyBGaW5hbCBNb2RlbCBTdW1tYXJ5CgpzdW1tYXJ5KFZBU19Nb2RlbF9maW5hbCkKY29uZmludChWQVNfTW9kZWxfZmluYWwpCgpgYGAKCiMgUmVzZWFyY2ggUTI6IFJlbGF0aW9uc2hpcCBiZXR3ZWVuIE9UIGFuZCBWQVMKCk1vZGVsIDEKYGBge3J9CgojIFNwZWNpZnkgTW9kZWwKCk9UX1ZBU19tb2RlbCA8LSBsbSh0cmFuc0FjYyB+IFZBUypFdGlvbG9neSArIFZBUypTZXgsIGRhdGEgPSBBY291c3RpY0RhdGEpCgojIEFzc3VtcHRpb24gQ2hlY2sKCnBlcmZvcm1hbmNlOjpjaGVja19tb2RlbChPVF9WQVNfbW9kZWwpCgojIE1vZGVsIFJlc3VsdHMKCnN1bW1hcnkoT1RfVkFTX21vZGVsKQoKYGBgCgojIyBGaW5hbCBMaW5lYXIgTW9kZWwKCmBgYHtyfQoKIyBTcGVjaWZ5IEZpbmFsIE1vZGVsCgpPVF9WQVNfZmluYWwgPC0gbG0odHJhbnNBY2MgfiBWQVMsIGRhdGEgPSBBY291c3RpY0RhdGEpCgpjb25maW50KE9UX1ZBU19maW5hbCkKCiMgTW9kZWwgUmVzdWx0cwoKc3VtbWFyeShPVF9WQVNfZmluYWwpCgpgYGAKCiMgQ29ybmVyIERpc3BlcnNpb24KTG9va2luZyBhdCBjb3JuZXIgZGlzcGVyc2lvbiBhcyB0aGUgc29sZSBwcmVkaWN0b3IuCgpgYGB7cn0KCiMgU3BlY2lmeSBGaW5hbCBNb2RlbAoKT1RfY29ybkRpc3AgPC0gbG0odHJhbnNBY2MgfiB2b3dlbF9FRF9iLCBkYXRhID0gQWNvdXN0aWNEYXRhKQpzdW1tYXJ5KE9UX2Nvcm5EaXNwKQoKVkFTX2Nvcm5EaXNwIDwtIGxtKFZBUyB+IHZvd2VsX0VEX2IsIGRhdGEgPSBBY291c3RpY0RhdGEpCnN1bW1hcnkoVkFTX2Nvcm5EaXNwKQoKYGBgCiMgTWFudXNjcmlwdCBUYWJsZXMKIyNEZXNjcmlwdGl2ZXMgVGFibGUKYGBge3J9Cmd0RGF0YSA8LSBBY291c3RpY0RhdGEgJT4lCiAgcmJpbmQoLixBY291c3RpY0RhdGEgJT4lCiAgICAgICAgICBkcGx5cjo6bXV0YXRlKEV0aW9sb2d5ID0gIkFsbCBFdGlvbG9naWVzIikpICU+JQogIHJiaW5kKC4sQWNvdXN0aWNEYXRhICU+JQogICAgICAgICAgcmJpbmQoLixBY291c3RpY0RhdGEgJT4lCiAgICAgICAgICBkcGx5cjo6bXV0YXRlKEV0aW9sb2d5ID0gIkFsbCBFdGlvbG9naWVzIikpICU+JQogICAgICAgICAgZHBseXI6Om11dGF0ZShTZXggPSAiQWxsIikpICU+JQogIGRwbHlyOjptdXRhdGUoU2V4ID0gYXMuZmFjdG9yKFNleCksCiAgICAgICAgICAgICAgICBFdGlvbG9neSA9IGFzLmZhY3RvcihFdGlvbG9neSkpICU+JQogIGRwbHlyOjpncm91cF9ieShTZXgsIEV0aW9sb2d5KSAlPiUKICBkcGx5cjo6c3VtbWFyaXplKFZTQV9tZWFuID0gbWVhbihWU0FfYiwgbmEucm0gPVQpLCBWU0Ffc2QgPSBzZChWU0FfYiwgbmEucm0gPSBUKSwKICAgICAgICAgICAgICAgICAgIERpc3BfbWVhbiA9IG1lYW4odm93ZWxfRURfYiwgbmEucm0gPVQpLCBEaXNwX3NkID0gc2Qodm93ZWxfRURfYiwgbmEucm0gPVQpLAogICAgICAgICAgICAgICAgICAgYXV0b1ZTQV9tZWFuID0gbWVhbihhdXRvVlNBLCBuYS5ybSA9VCksIGF1dG9WU0Ffc2QgPSBzZChhdXRvVlNBLCBuYS5ybSA9IFQpLAogICAgICAgICAgICAgICAgICAgSHVsbF9tZWFuID0gbWVhbihIdWxsX2IsIG5hLnJtID1UKSwgSHVsbF9zZCA9IHNkKEh1bGxfYiwgbmEucm0gPVQpLAogICAgICAgICAgICAgICAgICAgVlNEMjVfbWVhbiA9IG1lYW4oSHVsbF9iVlNEXzI1LCBuYS5ybSA9VCksIFZTRDI1X3NkID0gc2QoSHVsbF9iVlNEXzI1LCBuYS5ybSA9VCksCiAgICAgICAgICAgICAgICAgICBWU0Q1MF9tZWFuID0gbWVhbihIdWxsX2JWU0RfNTAsIG5hLnJtID1UKSwgVlNENTBfc2QgPSBzZChIdWxsX2JWU0RfNTAsIG5hLnJtID1UKSwKICAgICAgICAgICAgICAgICAgIFZTRDc1X21lYW4gPSBtZWFuKEh1bGxfYlZTRF83NSwgbmEucm0gPVQpLCBWU0Q3NV9zZCA9IHNkKEh1bGxfYlZTRF83NSwgbmEucm0gPVQpLAogICAgICAgICAgICAgICAgICAgVkFTX21lYW4gPSBtZWFuKFZBUywgbmEucm0gPVQpLCBWQVNfc2QgPSBzZChWQVMsIG5hLnJtID1UKSwKICAgICAgICAgICAgICAgICAgIE9UX21lYW4gPSBtZWFuKHRyYW5zQWNjLCBuYS5ybSA9VCksIE9UX3NkID0gc2QodHJhbnNBY2MsIG5hLnJtID1UKSkgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBWU0FfbWVhbjpPVF9zZCwgbmFtZXNfdG8gPSAiTWVhc3VyZSIsCiAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJWYWx1ZSIpICU+JQogIGRwbHlyOjptdXRhdGUoVmFsdWUgPSByb3VuZChWYWx1ZSwgZGlnaXRzID0gMiksCiAgICAgICAgICAgICAgICBtZWFuU0QgPSBpZmVsc2UoZ3JlcGwoIl9tZWFuIixNZWFzdXJlKSwiTSIsInNkIiksCiAgICAgICAgICAgICAgICBNZWFzdXJlID0gZ3N1YigiX21lYW4iLCIiLE1lYXN1cmUpLAogICAgICAgICAgICAgICAgTWVhc3VyZSA9IGdzdWIoIl9zZCIsIiIsTWVhc3VyZSksCiAgICAgICAgICAgICAgICBFdGlvbG9neSA9IHBhc3RlKEV0aW9sb2d5LG1lYW5TRCwgc2VwID0gIl8iKSwKICAgICAgICAgICAgICAgIFNleCA9IGNhc2Vfd2hlbigKICAgICAgICAgICAgICAgICAgU2V4ID09ICJBbGwiIH4gIkFsbCBTcGVha2VycyIsCiAgICAgICAgICAgICAgICAgIFNleCA9PSAiTSIgfiAiTWFsZSBTcGVha2VycyIsCiAgICAgICAgICAgICAgICAgIFNleCA9PSAiRiIgfiAiRmVtYWxlIFNwZWFrZXJzIgogICAgICAgICAgICAgICAgKSkgJT4lCiAgZHBseXI6OnNlbGVjdCghbWVhblNEKSAlPiUKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gRXRpb2xvZ3ksIHZhbHVlc19mcm9tID0gIlZhbHVlIikgJT4lCiAgZHBseXI6OmZpbHRlcihNZWFzdXJlICE9ICJWU0Q1MCIpCgpndERhdGEgJT4lCiAgZ3Q6Omd0KAogICAgcm93bmFtZV9jb2wgPSAiTWVhc3VyZSIsCiAgICBncm91cG5hbWVfY29sID0gIlNleCIsCiAgKSAlPiUKICBmbXRfbnVtYmVyKAogICAgY29sdW1ucyA9ICdBbGwgRXRpb2xvZ2llc19NJzpQRF9zZCwKICAgIGRlY2ltYWxzID0gMgogICkgJT4lCiAgdGFiX3NwYW5uZXIoCiAgICBsYWJlbCA9ICJBbGwgRXRpb2xvZ2llcyIsCiAgICBjb2x1bW5zID0gYygnQWxsIEV0aW9sb2dpZXNfTScsICdBbGwgRXRpb2xvZ2llc19zZCcpCiAgKSAlPiUKICAgIHRhYl9zcGFubmVyKAogICAgbGFiZWwgPSAiQUxTIiwKICAgIGNvbHVtbnMgPSBjKEFMU19NLCBBTFNfc2QpCiAgKSAlPiUKICB0YWJfc3Bhbm5lcigKICAgIGxhYmVsID0gIlBEIiwKICAgIGNvbHVtbnMgPSBjKFBEX00sIFBEX3NkKQogICkgJT4lCiAgdGFiX3NwYW5uZXIoCiAgICBsYWJlbCA9ICJIRCIsCiAgICBjb2x1bW5zID0gYyhIRF9NLCBIRF9zZCkKICApICU+JQogIHRhYl9zcGFubmVyKAogICAgbGFiZWwgPSAiQXRheGljIiwKICAgIGNvbHVtbnMgPSBjKEF0YXhpY19NLCBBdGF4aWNfc2QpCiAgKSAlPiUKICBndDo6Y29sc19tb3ZlX3RvX3N0YXJ0KAogICAgY29sdW1ucyA9IGMoJ0FsbCBFdGlvbG9naWVzX00nLCdBbGwgRXRpb2xvZ2llc19zZCcpCiAgKSAlPiUKICByb3dfZ3JvdXBfb3JkZXIoCiAgICBncm91cHMgPSBjKCJBbGwgU3BlYWtlcnMiLCAiRmVtYWxlIFNwZWFrZXJzIiwgIk1hbGUgU3BlYWtlcnMiKQogICAgKSAlPiUKICBjb2xzX2xhYmVsKAogICAgICdBbGwgRXRpb2xvZ2llc19NJyA9ICJNIiwKICAgICAnQWxsIEV0aW9sb2dpZXNfc2QnID0gIlNEIiwKICAgICBBTFNfTSA9ICJNIiwKICAgICBBTFNfc2QgPSAiU0QiLAogICAgIFBEX00gPSAiTSIsCiAgICAgUERfc2QgPSAiU0QiLAogICAgIEhEX00gPSAiTSIsCiAgICAgSERfc2QgPSAiU0QiLAogICAgIEF0YXhpY19NID0gIk0iLAogICAgIEF0YXhpY19zZCA9ICJTRCIKICApICU+JQogIGd0c2F2ZSgiRGVzY3JpcHRpdmVzVGFibGUuaHRtbCIsIHBhdGggPSAiVGFibGVzIikKCmBgYAoKIyMgT1QgTW9kZWwKYGBge3J9CnNqUGxvdDo6dGFiX21vZGVsKE9UX01vZGVsMSxPVF9Nb2RlbDIsT1RfTW9kZWwzLAogICAgICAgICAgICAgICAgICBPVF9Nb2RlbDQsIE9UX01vZGVsNSxPVF9Nb2RlbDYsIE9UX01vZGVsX2ZpbmFsLAogICAgICAgICAgICAgICAgICBzaG93LmNpID0gRiwKICAgICAgICAgICAgICAgICAgcC5zdHlsZSA9ICJzdGFycyIsCiAgICAgICAgICAgICAgICAgIGZpbGUgPSAiVGFibGVzL09UIE1vZGVscy5odG1sIikKYGBgCgojIyBWQVMgTW9kZWwKYGBge3J9CnNqUGxvdDo6dGFiX21vZGVsKFZBU19Nb2RlbDEsCiAgICAgICAgICAgICAgICAgIFZBU19Nb2RlbDIsCiAgICAgICAgICAgICAgICAgIFZBU19Nb2RlbDMsCiAgICAgICAgICAgICAgICAgIFZBU19Nb2RlbDQsCiAgICAgICAgICAgICAgICAgIFZBU19Nb2RlbDUsCiAgICAgICAgICAgICAgICAgIFZBU19Nb2RlbDYsCiAgICAgICAgICAgICAgICAgIFZBU19Nb2RlbF9maW5hbCwKICAgICAgICAgICAgICAgICAgc2hvdy5jaSA9IEYsCiAgICAgICAgICAgICAgICAgIHAuc3R5bGUgPSAic3RhcnMiLAogICAgICAgICAgICAgICAgICBmaWxlID0gIlRhYmxlcy9WQVMgTW9kZWxzLmh0bWwiKQpgYGAKCiMjIE9UIHZzLiBWQVMKYGBge3J9CnNqUGxvdDo6dGFiX21vZGVsKE9UX1ZBU19tb2RlbCxPVF9WQVNfZmluYWwsCiAgICAgICAgICAgICAgICAgIHNob3cuY2kgPSBGLAogICAgICAgICAgICAgICAgICBzaG93LnJlZmx2bCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgIHAuc3R5bGUgPSAic3RhcnMiLAogICAgICAgICAgICAgICAgICBmaWxlID0gIlRhYmxlcy9PVCBhbmQgVkFTIENvbXBhcmlzb24uaHRtbCIpCmBgYAoKIyBNYW51c2NyaXB0IEZpZ3VyZXMKIyMgRXhhbXBsZSBNZWFzdXJlcwpgYGB7cn0KZm9ybWFudENvbG9yIDwtICJncmV5Igpmb3JtYW50QWxwaGEgPC0gLjk1CmxpbmVDb2xvciA8LSAid2hpdGUiCmxpbmVBbHBoYSA8LSAuOAoKdm93ZWxEYXRhIDwtIHJpbzo6aW1wb3J0KCJQcmVwcGVkIERhdGEvVm93ZWwgRGF0YS5jc3YiKSAlPiUKICBkcGx5cjo6ZmlsdGVyKFNwZWFrZXIgPT0gIkFGOCIpCgogIFBpdGNoX1BSQUFUIDwtIGxpc3QuZmlsZXMocGF0aCA9IHBhc3RlKCJQcmVwcGVkIERhdGEvRXhhbXBsZSBEYXRhLyIsIHNlcCA9ICIiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm4gPSAiLlBpdGNoIiwgaWdub3JlLmNhc2UgPSBUKSAlPiUKICAgIHBhc3RlKCJQcmVwcGVkIERhdGEvRXhhbXBsZSBEYXRhLyIsLiwgc2VwID0gIiIpICU+JQogICAgcmVhZC5kZWxpbSguLCBoZWFkZXIgPSBGKSAlPiUKICAgIGRwbHlyOjpyZW5hbWUoUGl0Y2ggPSBWMSkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKFBpdGNoID0gZ3N1YigiLS11bmRlZmluZWQtLSIsTkEsUGl0Y2gpLAogICAgICAgICAgICAgICAgICBQaXRjaCA9IGFzLm51bWVyaWMoUGl0Y2gpKQogIAogIEZvcm1hbnRzX1BSQUFUIDwtIGxpc3QuZmlsZXMocGF0aCA9IHBhc3RlKCJQcmVwcGVkIERhdGEvRXhhbXBsZSBEYXRhLyIsIHNlcCA9ICIiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm4gPSAiX0Zvcm1hbnQiLCBpZ25vcmUuY2FzZSA9IFQpICU+JQogICAgcGFzdGUoIlByZXBwZWQgRGF0YS9FeGFtcGxlIERhdGEvIiwuLCBzZXAgPSAiIikgJT4lCiAgICByZWFkLmRlbGltKC4sIGhlYWRlciA9IFQpICU+JQogICAgZHBseXI6OnNlbGVjdCghYyhuZm9ybWFudHMsIEIxLkh6LiwgQjIuSHouLCBCMy5Iei4sIEY0Lkh6LiwgQjQuSHouLCBGNS5Iei4sIEI1Lkh6LikpICU+JQogICAgZHBseXI6OnJlbmFtZShUaW1lX3MgPSB0aW1lLnMuLAogICAgICAgICAgICAgICAgICBGMV9IeiA9IEYxLkh6LiwKICAgICAgICAgICAgICAgICAgRjJfSHogPSBGMi5Iei4sCiAgICAgICAgICAgICAgICAgIEYzX0h6ID0gRjMuSHouKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoRjFfSHogPSBpZmVsc2UoRjFfSHogPT0gMCwgTkEsIEYxX0h6KSwKICAgICAgICAgICAgICAgICAgRjJfSHogPSBpZmVsc2UoRjJfSHogPT0gMCwgTkEsIEYyX0h6KSwKICAgICAgICAgICAgICAgICAgRjNfSHogPSBpZmVsc2UoRjNfSHogPT0gMCwgTkEsIEYzX0h6KSkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKEYxX0h6ID0gYXMubnVtZXJpYyhGMV9IeiksCiAgICAgICAgICAgICAgICAgIEYyX0h6ID0gYXMubnVtZXJpYyhGMl9IeiksCiAgICAgICAgICAgICAgICAgIEYzX0h6ID0gc3VwcHJlc3NXYXJuaW5ncyhhcy5udW1lcmljKEYzX0h6KSksCiAgICAgICAgICAgICAgICAgIFRpbWVfbXMgPSBUaW1lX3MgLyAxMDAwLAogICAgICAgICAgICAgICAgICBGMV9rSHogPSBGMV9IeiAvIDEwMDAsCiAgICAgICAgICAgICAgICAgIEYyX2tIeiA9IEYyX0h6IC8gMTAwMCwKICAgICAgICAgICAgICAgICAgRjNfa0h6ID0gRjNfSHogLyAxMDAwKSAlPiUKICAgIGRwbHlyOjpzZWxlY3QoIVRpbWVfcykgJT4lCiAgICBkcGx5cjo6cmVsb2NhdGUoVGltZV9tcywgLmJlZm9yZSA9IEYxX0h6KSAlPiUKICAgIGNiaW5kKC4sUGl0Y2hfUFJBQVQpCiAgCiAgYyA8LSAyCiAgd2hpbGUoYyA8IE5ST1coRm9ybWFudHNfUFJBQVQpKXsKICAgIEZvcm1hbnRzX1BSQUFUJEYxX0h6W2NdIDwtIGlmZWxzZShpcy5uYShGb3JtYW50c19QUkFBVCRGMV9IeltjLTFdKSAmJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXMubmEoRm9ybWFudHNfUFJBQVQkRjFfSHpbYysxXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRm9ybWFudHNfUFJBQVQkRjFfSHpbY10pCiAgICBGb3JtYW50c19QUkFBVCRGMl9IeltjXSA8LSBpZmVsc2UoaXMubmEoRm9ybWFudHNfUFJBQVQkRjJfSHpbYy0xXSkgJiYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzLm5hKEZvcm1hbnRzX1BSQUFUJEYyX0h6W2MrMV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5BLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZvcm1hbnRzX1BSQUFUJEYyX0h6W2NdKQogICAgYyA8LSBjICsgMQogIH0KICBybShjKQogIAogIEZvcm1hbnRzX1BSQUFUIDwtIEZvcm1hbnRzX1BSQUFUICU+JQogICAgZHBseXI6OmZpbHRlcighaXMubmEoUGl0Y2gpKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoRjFfbWFkID0gKGFicyhGMV9IeiAtIG1lZGlhbihGMV9IeikpLyBtYWQoRjFfSHosIGNvbnN0YW50ID0gMS40ODI2KSkgPiAyLjUsCiAgICAgICAgICAgICAgICAgIEYyX21hZCA9IChhYnMoRjJfSHogLSBtZWRpYW4oRjJfSHopKS8gbWFkKEYyX0h6LCBjb25zdGFudCA9IDEuNDgyNikpID4gMi41KSAlPiUKICAgIGRwbHlyOjpmaWx0ZXIoRjFfbWFkID09IEZBTFNFICYgRjJfbWFkID09IEZBTFNFKSAlPiUKICAgIGRwbHlyOjptdXRhdGUobURpc3QgPSBtYWhhbGFub2JpcyhjYmluZCguJEYxX0h6LCAuJEYyX0h6KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xNZWFucyhjYmluZCguJEYxX0h6LCAuJEYyX0h6KSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY292ID0gY292KGNiaW5kKC4kRjFfSHosIC4kRjJfSHopKSksCiAgICAgICAgICAgICAgICAgIG1EaXN0X3NkID0gYWJzKHNjYWxlKG1EaXN0LGNlbnRlciA9IFQpKSkgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKG1EaXN0X3NkIDwgMikgJT4lCiAgICBkcGx5cjo6c2VsZWN0KCFjKEYxX21hZCwgRjJfbWFkLCBtRGlzdCwgbURpc3Rfc2QpKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoRjFfeiA9IHNjYWxlKEYxX0h6LCBjZW50ZXIgPSBUUlVFKSwKICAgICAgICAgICAgICAgICAgRjJfeiA9IHNjYWxlKEYyX0h6LCBjZW50ZXIgPSBUUlVFKSwKICAgICAgICAgICAgICAgICAgRjNfeiA9IHNjYWxlKEYzX0h6LCBjZW50ZXIgPSBUUlVFKSwKICAgICAgICAgICAgICAgICAgRjFfYiA9IGVtdVI6OmJhcmsoRjFfSHopLAogICAgICAgICAgICAgICAgICBGMl9iID0gZW11Ujo6YmFyayhGMl9IeiksCiAgICAgICAgICAgICAgICAgIEYzX2IgPSBlbXVSOjpiYXJrKEYzX0h6KSkKICAKICBybShQaXRjaF9QUkFBVCkKICAKICAKIyMgQ29ybmVyIERpc3BlcnNpb24gLS0tLQogIHdlZGdlIDwtIHZvd2VsRGF0YSAlPiUKICAgIGRwbHlyOjpncm91cF9ieShWb3dlbCkgJT4lCiAgICBkcGx5cjo6c3VtbWFyaXplKG1lYW5fRjEgPSBtZWFuKEYxX3RlbXBNaWQpLAogICAgICAgICAgICAgIG1lYW5fRjIgPSBtZWFuKEYyX3RlbXBNaWQpLAogICAgICAgICAgICAgIG1lYW5fRjFfeiA9IG1lYW4oRjFfel90ZW1wTWlkKSwKICAgICAgICAgICAgICBtZWFuX0YyX3ogPSBtZWFuKEYyX3pfdGVtcE1pZCksCiAgICAgICAgICAgICAgbWVhbl9GMV9iID0gbWVhbihGMV9iX3RlbXBNaWQpLAogICAgICAgICAgICAgIG1lYW5fRjJfYiA9IG1lYW4oRjJfYl90ZW1wTWlkKSkgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKFZvd2VsID09ICJ2IikKICAgIAogIGNvcm5lcl9kaXMgPC0gdm93ZWxEYXRhICU+JQogICAgZHBseXI6OmZpbHRlcihWb3dlbCAhPSAidiIpICU+JQogICAgZHBseXI6Omdyb3VwX2J5KFZvd2VsKSAlPiUKICAgIGRwbHlyOjpzdW1tYXJpemUobWVhbl9GMSA9IG1lYW4oRjFfdGVtcE1pZCksCiAgICAgICAgICAgICAgbWVhbl9GMiA9IG1lYW4oRjJfdGVtcE1pZCksCiAgICAgICAgICAgICAgbWVhbl9GMV96ID0gbWVhbihGMV96X3RlbXBNaWQpLAogICAgICAgICAgICAgIG1lYW5fRjJfeiA9IG1lYW4oRjJfel90ZW1wTWlkKSwKICAgICAgICAgICAgICBtZWFuX0YxX2IgPSBtZWFuKEYxX2JfdGVtcE1pZCksCiAgICAgICAgICAgICAgbWVhbl9GMl9iID0gbWVhbihGMl9iX3RlbXBNaWQpKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoVm93ZWxfRUQgPSBzcXJ0KChtZWFuX0YxLXdlZGdlJG1lYW5fRjEpXjIgKyAobWVhbl9GMi13ZWRnZSRtZWFuX0YyKV4yKSwKICAgICAgICAgICAgICAgICAgVm93ZWxfRURfeiA9IHNxcnQoKG1lYW5fRjFfei13ZWRnZSRtZWFuX0YxX3opXjIgKyAobWVhbl9GMl96LXdlZGdlJG1lYW5fRjJfeileMiksCiAgICAgICAgICAgICAgICAgIFZvd2VsX0VEX2IgPSBzcXJ0KChtZWFuX0YxX2Itd2VkZ2UkbWVhbl9GMV9iKV4yICsgKG1lYW5fRjJfYi13ZWRnZSRtZWFuX0YyX2IpXjIpKQoKICAgIAojIFBsb3QgQ29ybmVyIERpc3BlcnNpb24KICAgICAgIyBDaGFuZ2luZyB0byBJUEEgc3ltYm9scwogICAgICBjb3JuZXJfZGlzIDwtIGNvcm5lcl9kaXMgJT4lCiAgICAgICAgZHBseXI6Om11dGF0ZShWb3dlbCA9IGRwbHlyOjpjYXNlX3doZW4oCiAgICAgICAgICBWb3dlbCA9PSAiYWUiIH4gIsOmIiwKICAgICAgICAgIFRSVUUgfiBWb3dlbAogICAgICAgICkpCiAgICAgIAogICAgICB3ZWRnZSA8LSB3ZWRnZSAlPiUKICAgICAgICBkcGx5cjo6bXV0YXRlKFZvd2VsID0gY2FzZV93aGVuKAogICAgICAgICAgVm93ZWwgPT0gInYiIH4gIsqMIiwKICAgICAgICAgIFRSVUUgfiBWb3dlbAogICAgICAgICkpCiAgICAgIAogICAgICBDRHBsb3QgPC0gZ2dwbG90KGFlcyh4PUYyX2IsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHk9RjFfYiksCiAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IEZvcm1hbnRzX1BSQUFULAogICAgICAgICAgICAgICAgICAgICAgIGluaGVyaXQuYWVzID0gRkFMU0UpICsgCiAgICAgIGdlb21fcG9pbnQoc2hhcGUgPSAyMSwKICAgICAgICAgICAgICAgICBhbHBoYSA9IGZvcm1hbnRBbHBoYSwKICAgICAgICAgICAgICAgICBjb2xvciA9IGZvcm1hbnRDb2xvcikgKyAKICAgICAgZ2VvbV9saW5lKGFlcyh4ID0gbWVhbl9GMl9iLAogICAgICAgICAgICAgICAgICAgIHkgPSBtZWFuX0YxX2IpLAogICAgICAgICAgICAgICAgZGF0YSA9IGNvcm5lcl9kaXMgJT4lCiAgICAgICAgICAgICAgICAgIGRwbHlyOjpzZWxlY3QoVm93ZWw6bWVhbl9GMl9iKSAlPiUKICAgICAgICAgICAgICAgICAgZHBseXI6OmZpbHRlcihWb3dlbCA9PSAiaSIpICU+JQogICAgICAgICAgICAgICAgICByYmluZCguLHdlZGdlKSwKICAgICAgICAgICAgICAgIGNvbG9yID0gbGluZUNvbG9yLAogICAgICAgICAgICAgICAgc2l6ZSA9IDEuNSwKICAgICAgICAgICAgICAgIGFscGhhID0gbGluZUFscGhhKSArCiAgICAgIGdlb21fbGluZShhZXMoeCA9IG1lYW5fRjJfYiwKICAgICAgICAgICAgICAgICAgICB5ID0gbWVhbl9GMV9iKSwKICAgICAgICAgICAgICAgIGRhdGEgPSBjb3JuZXJfZGlzICU+JQogICAgICAgICAgICAgICAgICBkcGx5cjo6c2VsZWN0KFZvd2VsOm1lYW5fRjJfYikgJT4lCiAgICAgICAgICAgICAgICAgIGRwbHlyOjpmaWx0ZXIoVm93ZWwgPT0gImEiKSAlPiUKICAgICAgICAgICAgICAgICAgcmJpbmQoLix3ZWRnZSksCiAgICAgICAgICAgICAgICBjb2xvciA9IGxpbmVDb2xvciwKICAgICAgICAgICAgICAgIHNpemUgPSAxLjUsCiAgICAgICAgICAgICAgICBhbHBoYSA9IGxpbmVBbHBoYSkgKwogICAgICBnZW9tX2xpbmUoYWVzKHggPSBtZWFuX0YyX2IsCiAgICAgICAgICAgICAgICAgICAgeSA9IG1lYW5fRjFfYiksCiAgICAgICAgICAgICAgICBkYXRhID0gY29ybmVyX2RpcyAlPiUKICAgICAgICAgICAgICAgICAgZHBseXI6OnNlbGVjdChWb3dlbDptZWFuX0YyX2IpICU+JQogICAgICAgICAgICAgICAgICBkcGx5cjo6ZmlsdGVyKFZvd2VsID09ICLDpiIpICU+JQogICAgICAgICAgICAgICAgICByYmluZCguLHdlZGdlKSwKICAgICAgICAgICAgICAgIGNvbG9yID0gbGluZUNvbG9yLAogICAgICAgICAgICAgICAgc2l6ZSA9IDEuNSwKICAgICAgICAgICAgICAgIGFscGhhID0gbGluZUFscGhhKSArCiAgICAgIGdlb21fbGluZShhZXMoeCA9IG1lYW5fRjJfYiwKICAgICAgICAgICAgICAgICAgICB5ID0gbWVhbl9GMV9iKSwKICAgICAgICAgICAgICAgIGRhdGEgPSBjb3JuZXJfZGlzICU+JQogICAgICAgICAgICAgICAgICBkcGx5cjo6c2VsZWN0KFZvd2VsOm1lYW5fRjJfYikgJT4lCiAgICAgICAgICAgICAgICAgIGRwbHlyOjpmaWx0ZXIoVm93ZWwgPT0gInUiKSAlPiUKICAgICAgICAgICAgICAgICAgcmJpbmQoLix3ZWRnZSksCiAgICAgICAgICAgICAgICBjb2xvciA9IGxpbmVDb2xvciwKICAgICAgICAgICAgICAgIHNpemUgPSAxLjUsCiAgICAgICAgICAgICAgICBhbHBoYSA9IGxpbmVBbHBoYSkgKwogICAgICBnZW9tX3BvaW50KGFlcyh4ID0gbWVhbl9GMl9iLAogICAgICAgICAgICAgICAgICAgICB5ID0gbWVhbl9GMV9iLAogICAgICAgICAgICAgICAgICAgICBjb2xvciA9IFZvd2VsKSwKICAgICAgICAgICAgICAgICBkYXRhID0gY29ybmVyX2RpcyAlPiUKICAgICAgICAgICAgICAgICAgZHBseXI6OnNlbGVjdChWb3dlbDptZWFuX0YyX2IpICU+JQogICAgICAgICAgICAgICAgICByYmluZCguLHdlZGdlKSwKICAgICAgICAgICAgICAgICBpbmhlcml0LmFlcyA9IEZBTFNFLAogICAgICAgICAgICAgICAgIHNpemUgPSA1KSArCiAgICAgIHNjYWxlX3lfcmV2ZXJzZSgpICsKICAgICAgc2NhbGVfeF9yZXZlcnNlKCkgKwogICAgICB0aGVtZV9jbGFzc2ljKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoIkNvcm5lciBEaXNwZXJzaW9uIikpICsgeGxhYigiRjIgKGJhcmspIikgKyB5bGFiKCJGMSAoYmFyaykiKSArCiAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLAogICAgICAgICAgICBhc3BlY3QucmF0aW8gPSAxKSArCiAgICAgICAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiYSIgPSAiIzFBQUQ3NyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiw6YiID0gIiMxMjc5QjUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImkiID0gIiNGRkJGMDAiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInUiID0gIiNGRDc4NTMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIsqMIiA9ICIjQkYzMTc4IikpCiAgICBDRHBsb3QKICAgIAogICAgICBybShjb3JuZXJfZGlzLCB3ZWRnZSkKICAgICAgCiMjIFZvd2VsIFNwYWNlIEFyZWEgLS0tLQogIFZTQV9jb29yZHMgPC0gdm93ZWxEYXRhICU+JQogICAgZHBseXI6OmZpbHRlcihWb3dlbCAhPSAidiIpICU+JQogICAgZHBseXI6Omdyb3VwX2J5KFZvd2VsKSAlPiUKICAgIGRwbHlyOjpzdW1tYXJpemUobWVhbl9GMSA9IG1lYW4oRjFfdGVtcE1pZCksCiAgICAgICAgICAgICAgbWVhbl9GMiA9IG1lYW4oRjJfdGVtcE1pZCksCiAgICAgICAgICAgICAgbWVhbl9GMV96ID0gbWVhbihGMV96X3RlbXBNaWQpLAogICAgICAgICAgICAgIG1lYW5fRjJfeiA9IG1lYW4oRjJfel90ZW1wTWlkKSwKICAgICAgICAgICAgICBtZWFuX0YxX2IgPSBtZWFuKEYxX2JfdGVtcE1pZCksCiAgICAgICAgICAgICAgbWVhbl9GMl9iID0gbWVhbihGMl9iX3RlbXBNaWQpKSAKICAKIyMjIFBsb3R0aW5nIFZTQQogICAgVlNBX2Nvb3JkcyA8LSBWU0FfY29vcmRzICU+JQogICAgICAgIGRwbHlyOjptdXRhdGUoVm93ZWwgPSBjYXNlX3doZW4oCiAgICAgICAgICBWb3dlbCA9PSAiYWUiIH4gIsOmIiwKICAgICAgICAgIFRSVUUgfiBWb3dlbAogICAgICAgICkpCiAgICAKICAgIFZTQXBsb3QgPC0gZ2dwbG90KGFlcyh4ID0gRjJfYiwKICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gRjFfYiksCiAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gRm9ybWFudHNfUFJBQVQsCiAgICAgICAgICAgICAgICAgICAgICBpbmhlcml0LmFlcyA9IEZBTFNFKSArIAogICAgICBnZW9tX3BvaW50KHNoYXBlID0gMjEsCiAgICAgICAgICAgICAgICAgYWxwaGEgPSBmb3JtYW50QWxwaGEsCiAgICAgICAgICAgICAgICAgY29sb3IgPSBmb3JtYW50Q29sb3IpICsgCiAgICAgIGdlb21fcG9seWdvbihhZXMoeCA9IG1lYW5fRjJfYiwKICAgICAgICAgICAgICAgICAgICAgICB5ID0gbWVhbl9GMV9iKSwKICAgICAgICAgICAgICAgICAgIGRhdGEgPSBWU0FfY29vcmRzLAogICAgICAgICAgICAgICAgICAgYWxwaGEgPSBsaW5lQWxwaGEsCiAgICAgICAgICAgICAgICAgICBjb2xvciA9IGxpbmVDb2xvciwKICAgICAgICAgICAgICAgICAgIGZpbGw9TkEsCiAgICAgICAgICAgICAgICAgICBzaXplID0gMS41KSArCiAgICAgIGdlb21fcG9pbnQoYWVzKHggPSBtZWFuX0YyX2IsCiAgICAgICAgICAgICAgICAgICAgIHkgPSBtZWFuX0YxX2IsCiAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gVm93ZWwpLAogICAgICAgICAgICAgICAgIGRhdGEgPSBWU0FfY29vcmRzLAogICAgICAgICAgICAgICAgIGluaGVyaXQuYWVzID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgc2l6ZSA9IDUpICsKICAgICAgc2NhbGVfeV9yZXZlcnNlKCkgKwogICAgICBzY2FsZV94X3JldmVyc2UoKSArCiAgICAgIGd1aWRlcyhjb2xvciA9IEZBTFNFKSArCiAgICAgIHRoZW1lX2NsYXNzaWMoKSArIGxhYnModGl0bGUgPSAiVlNBIikgKyB4bGFiKCJGMiAoYmFyaykiKSArIHlsYWIoIkYxIChiYXJrKSIpICsKICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksCiAgICAgICAgICAgIGFzcGVjdC5yYXRpbyA9IDEpICsKICAgICAgICAgICAgICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJhIiA9ICIjMUFBRDc3IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICLDpiIgPSAiIzEyNzlCNSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiaSIgPSAiI0ZGQkYwMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAidSIgPSAiI0ZENzg1MyIpKQogICAgVlNBcGxvdAogIAogIHJtKFZTQV9jb29yZHMpCiAgCiMjIEF1dG9tYXRpYyBWU0EgLS0tLQogIFJlZkRhdGEgPC0gb3Blbnhsc3g6OnJlYWQueGxzeCgiUHJlcHBlZCBEYXRhL0V4YW1wbGUgRGF0YS9IaWxsZW5icmFuZCBWb3dlbCBEYXRhLnhsc3giLAogICAgICAgICAgICAgICAgICAgICBzaGVldCA9ICJIaWxsZW5icmFuZCBWb3dlbCBEYXRhIikgJT4lCiAgZHBseXI6OnJlbmFtZShTcGVha2VyID0gMSwKICAgICAgICAgICAgICAgIEYxX0h6ID0gNCwKICAgICAgICAgICAgICAgIEYyX0h6ID0gNSkgJT4lCiAgZHBseXI6OnNlbGVjdChTcGVha2VyLCBGMV9IeiwgRjJfSHopICU+JQogIGRwbHlyOjpmaWx0ZXIoIWdyZXBsKCJifGciLFNwZWFrZXIpKSAlPiUKICBkcGx5cjo6bXV0YXRlKEYxID0gZW11Ujo6YmFyayhGMV9IeiksCiAgICAgICAgICAgICAgICBGMiA9IGVtdVI6OmJhcmsoRjJfSHopLAogICAgICAgICAgICAgICAgU2V4ID0gaWZlbHNlKGdyZXBsKCJtIixTcGVha2VyKSwiTSIsIkYiKSwKICAgICAgICAgICAgICAgIFZvd2VsID0gY2FzZV93aGVuKAogICAgICAgICAgICAgICAgICBncmVwbChwYXR0ZXJuID0gInV3IiwgU3BlYWtlcikgfiAidSIsCiAgICAgICAgICAgICAgICAgIGdyZXBsKHBhdHRlcm4gPSAiYWgiLCBTcGVha2VyKSB+ICJhIiwKICAgICAgICAgICAgICAgICAgZ3JlcGwocGF0dGVybiA9ICJpeSIsIFNwZWFrZXIpIH4gImkiLAogICAgICAgICAgICAgICAgICBncmVwbChwYXR0ZXJuID0gInVoIiwgU3BlYWtlcikgfiAidiIsCiAgICAgICAgICAgICAgICAgIGdyZXBsKHBhdHRlcm4gPSAiYWUiLCBTcGVha2VyKSB+ICJhZSIsCiAgICAgICAgICAgICAgICAgIGdyZXBsKHBhdHRlcm4gPSAiYXciLCBTcGVha2VyKSB+ICLJlCIsCiAgICAgICAgICAgICAgICAgIGdyZXBsKHBhdHRlcm4gPSAiZWgiLCBTcGVha2VyKSB+ICLJmyIsCiAgICAgICAgICAgICAgICAgIGdyZXBsKHBhdHRlcm4gPSAiZXIiLCBTcGVha2VyKSB+ICLJnSIsCiAgICAgICAgICAgICAgICAgIGdyZXBsKHBhdHRlcm4gPSAiZWkiLCBTcGVha2VyKSB+ICJlyaoiLAogICAgICAgICAgICAgICAgICBncmVwbChwYXR0ZXJuID0gImloIiwgU3BlYWtlcikgfiAiyaoiLAogICAgICAgICAgICAgICAgICBncmVwbChwYXR0ZXJuID0gIm9hIiwgU3BlYWtlcikgfiAibyIsCiAgICAgICAgICAgICAgICAgIGdyZXBsKHBhdHRlcm4gPSAib28iLCBTcGVha2VyKSB+ICLKiiIKICAgICAgICAgICAgICAgICkpICU+JQogIGRwbHlyOjpmaWx0ZXIoIWlzLm5hKFZvd2VsKSkgJT4lCiAgZHBseXI6OnNlbGVjdCghU3BlYWtlcikgJT4lCiAgZHBseXI6Omdyb3VwX2J5KFNleCwgVm93ZWwpICU+JQogIGRwbHlyOjpzdW1tYXJpc2UoRjFfUmVmID0gbWVhbihGMSksCiAgICAgICAgICAgICAgICAgICBGMl9SZWYgPSBtZWFuKEYyKSkgJT4lCiAgICBkcGx5cjo6dW5ncm91cCgpICU+JQogICAgZHBseXI6OmZpbHRlcihTZXggPT0gIkYiKSAlPiUKICAgIGRwbHlyOjpzZWxlY3QoIWMoU2V4LCBWb3dlbCkpCiAgCiAgYXV0b1ZTQSA8LSBGb3JtYW50c19QUkFBVCAlPiUKICAgIGRwbHlyOjpzZWxlY3QoRjFfYixGMl9iKSAlPiUKICAgIHN0YXRzOjprbWVhbnMoLiwgY2VudGVycyA9IFJlZkRhdGEsIG5zdGFydCA9IDEwMCwgaXRlci5tYXggPSAxMDAwKSAlPiUKICAgIC4kY2VudGVycyAlPiUKICAgIGFzLmRhdGEuZnJhbWUoKQogIAogIGNvbnZleENvb3JkcyA8LSBhdXRvVlNBICU+JQogICAgYXMubWF0cml4KCkgJT4lCiAgICBnckRldmljZXM6OmNodWxsKCkKICAKICBhdXRvQ29udmV4IDwtIGF1dG9WU0EgJT4lCiAgICAgICAgc2xpY2UoY29udmV4Q29vcmRzKQogIAojIyMgUGxvdHRpbmcgQXV0b21hdGljIFZTQQogICAgYXV0b1ZTQXBsb3QgPC0gZ2dwbG90KGFlcyh4ID0gRjJfYiwKICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gRjFfYiksCiAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gRm9ybWFudHNfUFJBQVQsCiAgICAgICAgICAgICAgICAgICAgICBpbmhlcml0LmFlcyA9IEZBTFNFKSArIAogICAgICBnZW9tX3BvaW50KHNoYXBlID0gMjEsCiAgICAgICAgICAgICAgICAgYWxwaGEgPSBmb3JtYW50QWxwaGEsCiAgICAgICAgICAgICAgICAgY29sb3IgPSBmb3JtYW50Q29sb3IpICsgCiAgICAgIGdlb21fcG9seWdvbihhZXMoeCA9IEYyX2IsCiAgICAgICAgICAgICAgICAgICAgICAgeSA9IEYxX2IpLAogICAgICAgICAgICAgICAgICAgZGF0YSA9IGF1dG9Db252ZXgsCiAgICAgICAgICAgICAgICAgICBhbHBoYSA9IGxpbmVBbHBoYSwKICAgICAgICAgICAgICAgICAgIGNvbG9yID0gbGluZUNvbG9yLAogICAgICAgICAgICAgICAgICAgZmlsbD1OQSwKICAgICAgICAgICAgICAgICAgIHNpemUgPSAxLjUpICsKICAgICAgZ2VvbV9wb2ludChhZXMoeCA9IEYyX2IsCiAgICAgICAgICAgICAgICAgICAgIHkgPSBGMV9iKSwKICAgICAgICAgICAgICAgICBkYXRhID0gYXV0b1ZTQSwKICAgICAgICAgICAgICAgICBpbmhlcml0LmFlcyA9IEZBTFNFLAogICAgICAgICAgICAgICAgIHNpemUgPSAyKSArCiAgICAgIHNjYWxlX3lfcmV2ZXJzZSgpICsKICAgICAgc2NhbGVfeF9yZXZlcnNlKCkgKwogICAgICAjZ3VpZGVzKGNvbG9yID0gRkFMU0UpICsKICAgICAgdGhlbWVfY2xhc3NpYygpICsKICAgICAgbGFicyh0aXRsZSA9ICJBdXRvbWF0aWMgVlNBIikgKwogICAgICB4bGFiKCJGMiAoYmFyaykiKSArCiAgICAgIHlsYWIoIkYxIChiYXJrKSIpICsKICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksCiAgICAgICAgICAgIGFzcGVjdC5yYXRpbyA9IDEpCiAgICBhdXRvVlNBcGxvdAogIAogIHJtKFZTQV9jb29yZHMpCiAgCiMjIEh1bGwgLS0tLQojIyMgUGxvdHRpbmcgSHVsbAogICAgICBjb252ZXhDb29yZHMgPC0gRm9ybWFudHNfUFJBQVQgJT4lCiAgICAgICAgZHBseXI6OnNlbGVjdChGMV9iLCBGMl9iKSAlPiUKICAgICAgICBhcy5tYXRyaXgoKSAlPiUKICAgICAgICBnckRldmljZXM6OmNodWxsKCkKICAgICAgY29udmV4IDwtIEZvcm1hbnRzX1BSQUFUICU+JQogICAgICAgIHNsaWNlKGNvbnZleENvb3JkcykKCiAgICAgIGh1bGxQbG90IDwtIGdncGxvdChhZXMoRjJfYiwgRjFfYiksCiAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gRm9ybWFudHNfUFJBQVQpICsKICAgICAgICBnZW9tX3BvaW50KHNoYXBlID0gMjEsCiAgICAgICAgICAgICAgICAgYWxwaGEgPSBmb3JtYW50QWxwaGEsCiAgICAgICAgICAgICAgICAgY29sb3IgPSBmb3JtYW50Q29sb3IpICsKICAgICAgICBnZW9tX3BvbHlnb24oZGF0YSA9IGNvbnZleCwKICAgICAgICAgICAgICAgICAgICAgYWxwaGEgPSAuNSwKICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiIzEyNzlCNSIsCiAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSBOQSwKICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEuNSkgKwogICAgICAgIHNjYWxlX3lfcmV2ZXJzZSgpICsKICAgICAgICBzY2FsZV94X3JldmVyc2UoKSArCiAgICAgICAgdGhlbWVfY2xhc3NpYygpICsgbGFicyh0aXRsZSA9ICJWU0EgSHVsbCIpICsgeGxhYigiRjIgKGJhcmspIikgKyB5bGFiKCJGMSAoYmFyaykiKSArCiAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLAogICAgICAgICAgICBhc3BlY3QucmF0aW8gPSAxKQogICAgICBodWxsUGxvdAogICAgCiAgCiMjIFZvd2VsIFNwYWNlIERlbnNpdHkgLS0tLQoKIyBCYXJrIE5vcm1hbGl6ZWQgRGVuc2l0eSAtLS0tCiMgc2VsZWN0aW5nIHRoZSBiYW5kd2lkdGgKSF9ocGkgPC0ga3M6OkhwaSh4ID0gRm9ybWFudHNfUFJBQVRbLGMoIkYyX2IiLCJGMV9iIildLCBwaWxvdCA9ICJzYW1zZSIsIHByZSA9ICJzY2FsZSIsIGJpbm5lZCA9IFQpCgojIGNvbXB1dGUgMmQga2RlCmsgPC0ga2RlKHggPSBGb3JtYW50c19QUkFBVFssYygiRjJfYiIsIkYxX2IiKV0sCiAgICAgICAgIEggPSBIX2hwaSwKICAgICAgICAgYmlubmVkID0gVCwKICAgICAgICAgZ3JpZHNpemUgPSAyNTApCgojZGVuc2l0eSA8LSBrW1siZXN0aW1hdGUiXV0KCiMgQmVmb3JlIHdlIGNhbiBwbG90IHRoZSBkZW5zaXR5IGVzdGltYXRlIHdlIG5lZWQgdG8gbWVsdCBpdCBpbnRvIGxvbmcgZm9ybWF0Cm1hdC5tZWx0ZWQgPC0gZGF0YS50YWJsZTo6bWVsdChrJGVzdGltYXRlKQpuYW1lcyhtYXQubWVsdGVkKSA8LSBjKCJ4IiwgInkiLCAiZGVuc2l0eSIpCgojIFdlIG5lZWQgdG8gYWRkIHR3byBtb3JlIGNvbHVtcyB0byBwcmVzZXJ2ZSB0aGUgYXhlcyB1bml0cwptYXQubWVsdGVkJEYyLmIgPC0gcmVwKGskZXZhbC5wb2ludHNbWzFdXSwgdGltZXMgPSBucm93KGskZXN0aW1hdGUpKQptYXQubWVsdGVkJEYxLmIgPC0gcmVwKGskZXZhbC5wb2ludHNbWzJdXSwgZWFjaCA9IG5yb3coayRlc3RpbWF0ZSkpCm1hdC5tZWx0ZWQkZGVuc2l0eSA8LSBzY2FsZXM6OnJlc2NhbGUobWF0Lm1lbHRlZCRkZW5zaXR5LCB0byA9IGMoMCwgMSkpCgojIFZTRCAtIDI1Cm5WU0RfMjUgPC0gbWF0Lm1lbHRlZCAlPiUKICBkcGx5cjo6ZmlsdGVyKGRlbnNpdHkgPiAuMjUpICU+JQogIGRwbHlyOjpzZWxlY3QoRjIuYixGMS5iLCBkZW5zaXR5KSAlPiUKICBkcGx5cjo6cmVuYW1lKERlbnNpdHkgPSBkZW5zaXR5KQoKY29udmV4Q29vcmRzIDwtIG5WU0RfMjUgJT4lCiAgZHBseXI6OnNlbGVjdChGMi5iLCBGMS5iKSAlPiUKICBhcy5tYXRyaXgoKSAlPiUKICAjZ3JEZXZpY2VzOjp4eS5jb29yZHMoKSAlPiUKICBnckRldmljZXM6OmNodWxsKCkKbmNvbnZleF8yNSA8LSBuVlNEXzI1ICU+JQogIHNsaWNlKGNvbnZleENvb3JkcykKCiMgVlNEIC0gNzUKblZTRF83NSA8LSBtYXQubWVsdGVkICU+JQogIGRwbHlyOjpmaWx0ZXIoZGVuc2l0eSA+IC43NSkgJT4lCiAgZHBseXI6OnNlbGVjdChGMi5iLEYxLmIsIGRlbnNpdHkpICU+JQogIGRwbHlyOjpyZW5hbWUoRGVuc2l0eSA9IGRlbnNpdHkpCgpjb252ZXhDb29yZHMgPC0gblZTRF83NSAlPiUKICBkcGx5cjo6c2VsZWN0KEYyLmIsIEYxLmIpICU+JQogIGFzLm1hdHJpeCgpICU+JQogIGdyRGV2aWNlczo6Y2h1bGwoKQpuY29udmV4Xzc1IDwtIG5WU0RfNzUgJT4lCiAgc2xpY2UoY29udmV4Q29vcmRzKQoKIyBQbG90dGluZyBaIE5vcm1hbGl6ZWQgVlNEIAogICAgcmYgPC0gY29sb3JSYW1wUGFsZXR0ZShyZXYoUkNvbG9yQnJld2VyOjpicmV3ZXIucGFsKDExLCAiU3BlY3RyYWwiKSkpCiAgICByIDwtIHJmKDMyKQogICAgCiAgICBwbG90RGF0YSA8LSBtYXQubWVsdGVkICU+JQogICAgICAgICAgICAgICAgICAgICAgICBkcGx5cjo6cmVuYW1lKERlbnNpdHkgPSBkZW5zaXR5KSAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgZHBseXI6Om11dGF0ZShWU0RsYWJlbCA9IGRwbHlyOjpjYXNlX3doZW4oCiAgICAgICAgICAgICAgICAgICAgICAgICAgRGVuc2l0eSA8IC4yNSB+ICJub25lIiwKICAgICAgICAgICAgICAgICAgICAgICAgICBEZW5zaXR5ID4gLjI1ICYmIERlbnNpdHkgPCAuNzUgfiAiVlNEMjUiLAogICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiVlNENzUiCiAgICAgICAgICAgICAgICAgICAgICAgICkpCmdlb20udGV4dC5zaXplIDwtIDIKICAgIFZTRHBsb3QgPC0gZ2dwbG90KGRhdGEgPSBwbG90RGF0YSwKICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gRjIuYiwKICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gRjEuYiwKICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxsID0gRGVuc2l0eSkpICsgCiAgICAgIGdlb21fdGlsZSgpICsgCiAgICAgIHNjYWxlX2ZpbGxfdmlyaWRpc19jKCkgKwogICAgICBzY2FsZV94X3JldmVyc2UoZXhwYW5kID0gYygwLCAwKSwgCiAgICAgICAgICAgICAgICAgICAgICBicmVha3MgPSByb3VuZChzZXEobWluKG1hdC5tZWx0ZWQkRjIuYiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heChtYXQubWVsdGVkJEYyLmIpLCBieSA9IDIpKSkgKwogICAgICBzY2FsZV95X3JldmVyc2UoZXhwYW5kID0gYygwLCAwKSwKICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IHJvdW5kKHNlcShtaW4obWF0Lm1lbHRlZCRGMS5iKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXgobWF0Lm1lbHRlZCRGMS5iKSwgYnkgPSAyKSkpICsgCiAgICAgIHlsYWIoIkYxIChiYXJrKSIpICsgeGxhYigiRjIgKGJhcmspIikgKwogICAgICBsYWJzKHRpdGxlID0gIlZTRCBIdWxsIikgKwogICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwKICAgICAgICAgICAgYXNwZWN0LnJhdGlvID0gMSkgKwogICAgICBnZW9tX3BvbHlnb24oZGF0YSA9IG5jb252ZXhfMjUsIGFscGhhID0gbGluZUFscGhhLCBjb2xvciA9IGxpbmVDb2xvciwgc2l6ZSA9IDEuNSwgZmlsbCA9IE5BLCBsaW5ldHlwZSA9IDIpICsKICAgICAgZ2VvbV9wb2x5Z29uKGRhdGEgPSBuY29udmV4Xzc1LCBhbHBoYSA9IGxpbmVBbHBoYSwgY29sb3IgPSBsaW5lQ29sb3IsIHNpemUgPSAxLjUsIGZpbGwgPSBOQSwgbGluZXR5cGUgPSAxKSArCiAgICAjIFZTRCAyNSBMYWJlbAogICAgICBhbm5vdGF0ZShnZW9tID0gImN1cnZlIiwKICAgICAgICAgICAgICAgeCA9IDYuOSwgeSA9IDEuNysuNSwKICAgICAgICAgICAgICAgeGVuZCA9IDguNSwgeWVuZCA9IDMuNSwKICAgICAgICAgICAgICAgY3VydmF0dXJlID0gLS4zLAogICAgICAgICAgICAgICBhcnJvdyA9IGFycm93KGxlbmd0aCA9IHVuaXQoMiwgIm1tIikpLAogICAgICAgICAgICAgICBjb2xvciA9ICJ3aGl0ZSIpICsKICAgICAgYW5ub3RhdGUoZ2VvbSA9ICJ0ZXh0IiwKICAgICAgICAgICAgICAgeCA9IDcuNSwgeSA9IDEuNywKICAgICAgICAgICAgICAgbGFiZWwgPSBkZXBhcnNlKGJxdW90ZShWU0RbMjVdKSksCiAgICAgICAgICAgICAgIGhqdXN0ID0gImNlbnRlciIsCiAgICAgICAgICAgICAgIGNvbG9yID0gIndoaXRlIiwKICAgICAgICAgICAgICAgcGFyc2U9VFJVRSkgKwogICAgIyBWU0QgNzUgTGFiZWwKICAgICAgYW5ub3RhdGUoZ2VvbSA9ICJjdXJ2ZSIsCiAgICAgICAgICAgICAgIHggPSA3LjUsIHkgPSA3LjUtLjUsCiAgICAgICAgICAgICAgIHhlbmQgPSAxMS4zNSwgeWVuZCA9IDUuNSwKICAgICAgICAgICAgICAgY3VydmF0dXJlID0gLjMsCiAgICAgICAgICAgICAgIGFycm93ID0gYXJyb3cobGVuZ3RoID0gdW5pdCgyLCAibW0iKSksCiAgICAgICAgICAgICAgIGNvbG9yID0gIndoaXRlIikgKwogICAgICBhbm5vdGF0ZShnZW9tID0gInRleHQiLAogICAgICAgICAgICAgICB4ID0gNywgeSA9IDcuNSwKICAgICAgICAgICAgICAgbGFiZWwgPSBkZXBhcnNlKGJxdW90ZShWU0RbNzVdKSksCiAgICAgICAgICAgICAgIGhqdXN0ID0gImNlbnRlciIsCiAgICAgICAgICAgICAgIGNvbG9yID0gIndoaXRlIiwKICAgICAgICAgICAgICAgcGFyc2UgPSBUUlVFKQogICAgIFZTRHBsb3QKCiMgQ29tYmluZWQgUGxvdAogICAgIAogICAgIHJvdzEgPC0gVlNBcGxvdCArIENEcGxvdCArCiAgICAgICAgcGF0Y2h3b3JrOjpwbG90X2xheW91dChndWlkZXMgPSAnY29sbGVjdCcsCiAgICAgICAgICAgICAgICAgICAgICAgICBuY29sID0gMikgJiB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAncmlnaHQnKQogICAgIHJvdzIgPC0gYXV0b1ZTQXBsb3QgKyBodWxsUGxvdCArIFZTRHBsb3QgKwogICAgICAgIHBhdGNod29yazo6cGxvdF9sYXlvdXQoZ3VpZGVzID0gJ2NvbGxlY3QnLAogICAgICAgICAgICAgICAgICAgICAgICAgbmNvbCA9IDMpICYgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gJ3JpZ2h0JykKICAgICAKICAgICBtZWFzdXJlc1Bsb3QgPC0gcm93MSAvIHJvdzIgKyBwYXRjaHdvcms6OnBsb3RfbGF5b3V0KGhlaWdodHMgPSBjKDEvMiwgMS8yKSwgYnlyb3cgPSBGQUxTRSkKICAgICBtZWFzdXJlc1Bsb3QKICAgICAKICAgICBybShyb3cxLCByb3cyKQoKZ2dzYXZlKGZpbGVuYW1lID0gIlBsb3RzL01lYXN1cmVzLnBuZyIsCiAgICAgICBwbG90ID0gbWVhc3VyZXNQbG90LAogICAgICAgaGVpZ2h0ID0gNS41LAogICAgICAgd2lkdGggPSA4LAogICAgICAgc2NhbGUgPSAuOCkKCmBgYAoKIyMgRmlsdGVyaW5nIFByb2Nlc3MKYGBge3J9CmZvcm1hbnRBbHBoYSA8LSAuMjAKbXlQYWwgPC0gYygiIzEyNzlCNSIsIiMyRDJEMzciKQoKUGl0Y2hfUFJBQVQgPC0gbGlzdC5maWxlcyhwYXRoID0gcGFzdGUoIlByZXBwZWQgRGF0YS9FeGFtcGxlIERhdGEvIiwgc2VwID0gIiIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVybiA9ICIuUGl0Y2giLCBpZ25vcmUuY2FzZSA9IFQpICU+JQogICAgcGFzdGUoIlByZXBwZWQgRGF0YS9FeGFtcGxlIERhdGEvIiwuLCBzZXAgPSAiIikgJT4lCiAgICByZWFkLmRlbGltKC4sIGhlYWRlciA9IEYpICU+JQogICAgZHBseXI6OnJlbmFtZShQaXRjaCA9IFYxKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoUGl0Y2ggPSBnc3ViKCItLXVuZGVmaW5lZC0tIixOQSxQaXRjaCksCiAgICAgICAgICAgICAgICAgIFBpdGNoID0gYXMubnVtZXJpYyhQaXRjaCkpCgpGb3JtYW50c19QUkFBVCA8LSBsaXN0LmZpbGVzKHBhdGggPSBwYXN0ZSgiUHJlcHBlZCBEYXRhL0V4YW1wbGUgRGF0YS8iLCBzZXAgPSAiIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuID0gIl9Gb3JtYW50IiwgaWdub3JlLmNhc2UgPSBUKSAlPiUKICAgIHBhc3RlKCJQcmVwcGVkIERhdGEvRXhhbXBsZSBEYXRhLyIsLiwgc2VwID0gIiIpICU+JQogICAgcmVhZC5kZWxpbSguLCBoZWFkZXIgPSBUKSAlPiUKICAgIGRwbHlyOjpzZWxlY3QoIWMobmZvcm1hbnRzLCBCMS5Iei4sIEIyLkh6LiwgQjMuSHouLCBGNC5Iei4sIEI0Lkh6LiwgRjUuSHouLCBCNS5Iei4pKSAlPiUKICAgIGRwbHlyOjpyZW5hbWUoVGltZV9zID0gdGltZS5zLiwKICAgICAgICAgICAgICAgICAgRjFfSHogPSBGMS5Iei4sCiAgICAgICAgICAgICAgICAgIEYyX0h6ID0gRjIuSHouLAogICAgICAgICAgICAgICAgICBGM19IeiA9IEYzLkh6LikgJT4lCiAgICBkcGx5cjo6bXV0YXRlKEYxX0h6ID0gaWZlbHNlKEYxX0h6ID09IDAsIE5BLCBGMV9IeiksCiAgICAgICAgICAgICAgICAgIEYyX0h6ID0gaWZlbHNlKEYyX0h6ID09IDAsIE5BLCBGMl9IeiksCiAgICAgICAgICAgICAgICAgIEYzX0h6ID0gaWZlbHNlKEYzX0h6ID09IDAsIE5BLCBGM19IeikpICU+JQogICAgZHBseXI6Om11dGF0ZShGMV9IeiA9IGFzLm51bWVyaWMoRjFfSHopLAogICAgICAgICAgICAgICAgICBGMl9IeiA9IGFzLm51bWVyaWMoRjJfSHopLAogICAgICAgICAgICAgICAgICBGM19IeiA9IHN1cHByZXNzV2FybmluZ3MoYXMubnVtZXJpYyhGM19IeikpLAogICAgICAgICAgICAgICAgICBUaW1lX21zID0gVGltZV9zIC8gMTAwMCwKICAgICAgICAgICAgICAgICAgRjFfa0h6ID0gRjFfSHogLyAxMDAwLAogICAgICAgICAgICAgICAgICBGMl9rSHogPSBGMl9IeiAvIDEwMDAsCiAgICAgICAgICAgICAgICAgIEYzX2tIeiA9IEYzX0h6IC8gMTAwMCwKICAgICAgICAgICAgICAgICAgRjFfYiA9IGVtdVI6OmJhcmsoRjFfSHopLAogICAgICAgICAgICAgICAgICBGMl9iID0gZW11Ujo6YmFyayhGMl9IeiksCiAgICAgICAgICAgICAgICAgIEYzX2IgPSBlbXVSOjpiYXJrKEYzX0h6KSkgJT4lCiAgICBkcGx5cjo6c2VsZWN0KCFUaW1lX3MpICU+JQogICAgZHBseXI6OnJlbG9jYXRlKFRpbWVfbXMsIC5iZWZvcmUgPSBGMV9IeikgJT4lCiAgICBjYmluZCguLFBpdGNoX1BSQUFUKQogIAogIGMgPC0gMgogIHdoaWxlKGMgPCBOUk9XKEZvcm1hbnRzX1BSQUFUKSl7CiAgICBGb3JtYW50c19QUkFBVCRGMV9IeltjXSA8LSBpZmVsc2UoaXMubmEoRm9ybWFudHNfUFJBQVQkRjFfSHpbYy0xXSkgJiYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzLm5hKEZvcm1hbnRzX1BSQUFUJEYxX0h6W2MrMV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5BLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZvcm1hbnRzX1BSQUFUJEYxX0h6W2NdKQogICAgRm9ybWFudHNfUFJBQVQkRjJfSHpbY10gPC0gaWZlbHNlKGlzLm5hKEZvcm1hbnRzX1BSQUFUJEYyX0h6W2MtMV0pICYmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpcy5uYShGb3JtYW50c19QUkFBVCRGMl9IeltjKzFdKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOQSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGb3JtYW50c19QUkFBVCRGMl9IeltjXSkKICAgIGMgPC0gYyArIDEKICB9CiAgcm0oYykKICAKICAjIFJhdyBGb3JtYW50cyAtLS0tCiAgZjEgPC0gZ2dwbG90KGFlcyh4PUYyX2IsCiAgICAgICAgICAgICAgICAgICB5PUYxX2IpLAogICAgICAgICAgICAgICBkYXRhID0gRm9ybWFudHNfUFJBQVQpICsgCiAgICAgIGdlb21fcG9pbnQoc2hhcGUgPSAyMSwgY29sb3IgPSBteVBhbFsyXSkgKwogICAgICBzY2FsZV95X3JldmVyc2UoKSArCiAgICAgIHNjYWxlX3hfcmV2ZXJzZSgpICsKICAgICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IG15UGFsKSArCiAgICAgIHRoZW1lX2NsYXNzaWMoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgiUmF3IEZvcm1hbnQgVmFsdWVzIikpICsgeGxhYigiRjIgKGJhcmspIikgKyB5bGFiKCJGMSAoYmFyaykiKSArCiAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLAogICAgICAgICAgICBhc3BlY3QucmF0aW8gPSAxLAogICAgICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTIpKQogICAgCiMgU3RlcCAjMTogVm9pY2VkIFNlZ21lbnRzIC0tLS0KICAgIHBsb3REYXRhIDwtIEZvcm1hbnRzX1BSQUFUICU+JQogICAgICAgICAgICAgICAgICAgZHBseXI6Om11dGF0ZShpc091dGxpZXIgPSBjYXNlX3doZW4oCiAgICAgICAgICAgICAgICAgICAgIGlzLm5hKFBpdGNoKSB+ICJSZW1vdmVkIiwKICAgICAgICAgICAgICAgICAgICAgVFJVRSB+ICJSZXRhaW5lZCIKICAgICAgICAgICAgICAgICAgICkpCiAgICBmMiA8LSBnZ3Bsb3QoZGF0YSA9IHBsb3REYXRhLAogICAgICAgICAgICAgICAgIGFlcyh4ID0gRjJfYiwKICAgICAgICAgICAgICAgICAgICAgeSA9IEYxX2IsCiAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gaXNPdXRsaWVyKSkgKyAKICAgICAgZ2VvbV9wb2ludChzaGFwZSA9IDIxLCBkYXRhID0gcGxvdERhdGEgJT4lCiAgICAgICAgICAgICAgICAgICBkcGx5cjo6ZmlsdGVyKGlzT3V0bGllciA9PSAiUmVtb3ZlZCIpKSArCiAgICAgIGdlb21fcG9pbnQoc2hhcGUgPSAyMSwgZGF0YSA9IHBsb3REYXRhICU+JQogICAgICAgICAgICAgZHBseXI6OmZpbHRlcihpc091dGxpZXIgPT0gIlJldGFpbmVkIikpICsKICAgICAgc2NhbGVfeV9yZXZlcnNlKCkgKwogICAgICBzY2FsZV94X3JldmVyc2UoKSArCiAgICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBteVBhbCkgKwogICAgICB0aGVtZV9jbGFzc2ljKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoIlN0ZXAgIzE6XG5Wb2ljZWQgU2VnbWVudHMiKSkgKwogICAgICB4bGFiKCJGMiAoYmFyaykiKSArCiAgICAgIHlsYWIoIkYxIChiYXJrKSIpICsKICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksCiAgICAgICAgICAgIGFzcGVjdC5yYXRpbyA9IDEsCiAgICAgICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0xMikpCiAgICAKIyBTdGVwIDI6IE1BRCAtLS0tCiAgICBwbG90RGF0YSA8LSBGb3JtYW50c19QUkFBVCAlPiUKICAgICAgZHBseXI6OmZpbHRlcighaXMubmEoUGl0Y2gpKSAlPiUKICAgICAgZHBseXI6Om11dGF0ZShGMV9tYWQgPSAoYWJzKEYxX0h6IC0gbWVkaWFuKEYxX0h6KSkvIG1hZChGMV9IeiwgY29uc3RhbnQgPSAxLjQ4MjYpKSA+IDIuNSwKICAgICAgICAgICAgICAgICAgICBGMl9tYWQgPSAoYWJzKEYyX0h6IC0gbWVkaWFuKEYyX0h6KSkvIG1hZChGMl9IeiwgY29uc3RhbnQgPSAxLjQ4MjYpKSA+IDIuNSwKICAgICAgICAgICAgICAgICAgICBpc091dGxpZXIgPSBjYXNlX3doZW4oCiAgICAgICAgICAgICAgICAgICAgICBGMV9tYWQgPT0gVFJVRSB8IEYyX21hZCA9PSBUUlVFIH4gIlJlbW92ZWQiLAogICAgICAgICAgICAgICAgICAgICAgVFJVRSB+ICJSZXRhaW5lZCIKICAgICAgICAgICAgICAgKSkKICAgIAogICAgZjMgPC0gZ2dwbG90KGRhdGEgPSBwbG90RGF0YSwKICAgICAgICAgICAgICAgICBhZXMoeCA9IEYyX2IsCiAgICAgICAgICAgICAgICAgICAgIHkgPSBGMV9iLAogICAgICAgICAgICAgICAgICAgICBjb2xvciA9IGlzT3V0bGllcikpICsgCiAgICAgIGdlb21fcG9pbnQoc2hhcGUgPSAyMSwgZGF0YSA9IHBsb3REYXRhICU+JQogICAgICAgICAgICAgICAgICAgZHBseXI6OmZpbHRlcihpc091dGxpZXIgPT0gIlJlbW92ZWQiKSkgKwogICAgICBnZW9tX3BvaW50KHNoYXBlID0gMjEsIGRhdGEgPSBwbG90RGF0YSAlPiUKICAgICAgICAgICAgIGRwbHlyOjpmaWx0ZXIoaXNPdXRsaWVyID09ICJSZXRhaW5lZCIpKSArCiAgICAgIHNjYWxlX3lfcmV2ZXJzZSgpICsKICAgICAgc2NhbGVfeF9yZXZlcnNlKCkgKwogICAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gbXlQYWwpICsKICAgICAgdGhlbWVfY2xhc3NpYygpICsKICAgICAgbGFicyh0aXRsZSA9IHBhc3RlKCJTdGVwICMyOlxuTWVkaWFuIEFic29sdXRlIERldmlhdGlvbiIpKSArCiAgICAgIHhsYWIoIkYyIChiYXJrKSIpICsKICAgICAgeWxhYigiRjEgKGJhcmspIikgKwogICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwKICAgICAgICAgICAgYXNwZWN0LnJhdGlvID0gMSwKICAgICAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTEyKSkKICAgIAojIFN0ZXAgMzogTWFoYWxhbmhvYmlzIERpc3RhbmNlIC0tLS0KICBwbG90RGF0YSA8LSBGb3JtYW50c19QUkFBVCAlPiUKICAgICAgZHBseXI6OmZpbHRlcighaXMubmEoUGl0Y2gpKSAlPiUKICAgICAgZHBseXI6Om11dGF0ZShGMV9tYWQgPSAoYWJzKEYxX0h6IC0gbWVkaWFuKEYxX0h6KSkvIG1hZChGMV9IeiwgY29uc3RhbnQgPSAxLjQ4MjYpKSA+IDIuNSwKICAgICAgICAgICAgICAgICAgICBGMl9tYWQgPSAoYWJzKEYyX0h6IC0gbWVkaWFuKEYyX0h6KSkvIG1hZChGMl9IeiwgY29uc3RhbnQgPSAxLjQ4MjYpKSA+IDIuNSkgJT4lCiAgICAgIGRwbHlyOjpmaWx0ZXIoRjFfbWFkID09IEZBTFNFICYgRjJfbWFkID09IEZBTFNFKSAlPiUKICAgICAgZHBseXI6Om11dGF0ZShtRGlzdCA9IG1haGFsYW5vYmlzKGNiaW5kKC4kRjFfSHosIC4kRjJfSHopLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbE1lYW5zKGNiaW5kKC4kRjFfSHosIC4kRjJfSHopKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3YgPSBjb3YoY2JpbmQoLiRGMV9IeiwgLiRGMl9IeikpKSwKICAgICAgICAgICAgICAgICAgbURpc3Rfc2QgPSBhYnMoc2NhbGUobURpc3QsY2VudGVyID0gVCkpLAogICAgICAgICAgICAgICAgICBpc091dGxpZXIgPSBjYXNlX3doZW4oCiAgICAgICAgICAgICAgICAgICAgbURpc3Rfc2QgPCAyIH4gIlJldGFpbmVkIiwKICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIlJlbW92ZWQiCiAgICAgICAgICAgICAgICAgICkpCiAgICAKICAgIGY0IDwtIGdncGxvdChkYXRhID0gcGxvdERhdGEsCiAgICAgICAgICAgICAgICAgYWVzKHggPSBGMl9iLAogICAgICAgICAgICAgICAgICAgICB5ID0gRjFfYiwKICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSBpc091dGxpZXIpKSArIAogICAgICBnZW9tX3BvaW50KHNoYXBlID0gMjEsIGRhdGEgPSBwbG90RGF0YSAlPiUKICAgICAgICAgICAgICAgICAgIGRwbHlyOjpmaWx0ZXIoaXNPdXRsaWVyID09ICJSZW1vdmVkIikpICsKICAgICAgZ2VvbV9wb2ludChzaGFwZSA9IDIxLCBkYXRhID0gcGxvdERhdGEgJT4lCiAgICAgICAgICAgICBkcGx5cjo6ZmlsdGVyKGlzT3V0bGllciA9PSAiUmV0YWluZWQiKSkgKwogICAgICBzY2FsZV95X3JldmVyc2UoKSArCiAgICAgIHNjYWxlX3hfcmV2ZXJzZSgpICsKICAgICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IG15UGFsKSArCiAgICAgIHRoZW1lX2NsYXNzaWMoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgiU3RlcCAjMzpcbk1haGFsYW5vYmlzIERpc3RhbmNlIikpICsgeGxhYigiRjIgKGJhcmspIikgKyB5bGFiKCJGMSAoYmFyaykiKSArCiAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLAogICAgICAgICAgICBhc3BlY3QucmF0aW8gPSAxLAogICAgICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTIpKQogICAgCiMgRmluYWwgRm9ybWFudHMgLS0tLQogICAgcGxvdERhdGEgPC0gRm9ybWFudHNfUFJBQVQgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKCFpcy5uYShQaXRjaCkpICU+JQogICAgZHBseXI6Om11dGF0ZShGMV9tYWQgPSAoYWJzKEYxX0h6IC0gbWVkaWFuKEYxX0h6KSkvIG1hZChGMV9IeiwgY29uc3RhbnQgPSAxLjQ4MjYpKSA+IDIuNSwKICAgICAgICAgICAgICAgICAgRjJfbWFkID0gKGFicyhGMl9IeiAtIG1lZGlhbihGMl9IeikpLyBtYWQoRjJfSHosIGNvbnN0YW50ID0gMS40ODI2KSkgPiAyLjUpICU+JQogICAgZHBseXI6OmZpbHRlcihGMV9tYWQgPT0gRkFMU0UgJiBGMl9tYWQgPT0gRkFMU0UpICU+JQogICAgZHBseXI6Om11dGF0ZShtRGlzdCA9IG1haGFsYW5vYmlzKGNiaW5kKC4kRjFfSHosIC4kRjJfSHopLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbE1lYW5zKGNiaW5kKC4kRjFfSHosIC4kRjJfSHopKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3YgPSBjb3YoY2JpbmQoLiRGMV9IeiwgLiRGMl9IeikpKSwKICAgICAgICAgICAgICAgICAgbURpc3Rfc2QgPSBhYnMoc2NhbGUobURpc3QsY2VudGVyID0gVCkpKSAlPiUKICAgIGRwbHlyOjpmaWx0ZXIobURpc3Rfc2QgPCAyKQogICAgCiAgICBmNSA8LSBnZ3Bsb3QoYWVzKHg9RjJfYiwKICAgICAgICAgICAgICAgICAgICAgeT1GMV9iKSwKICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gcGxvdERhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgaW5oZXJpdC5hZXMgPSBGQUxTRSkgKyAKICAgICAgZ2VvbV9wb2ludChzaGFwZSA9IDIxLCBjb2xvciA9IG15UGFsWzJdKSArIAogICAgICBzY2FsZV95X3JldmVyc2UoKSArCiAgICAgIHNjYWxlX3hfcmV2ZXJzZSgpICsKICAgICAgdGhlbWVfY2xhc3NpYygpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJGaW5hbCBGb3JtYW50IFZhbHVlcyIpKSArIHhsYWIoIkYyIChiYXJrKSIpICsgeWxhYigiRjEgKGJhcmspIikgKwogICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwKICAgICAgICAgICAgYXNwZWN0LnJhdGlvID0gMSwgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpKQogICAgCiMgQ29taWJpbmcgcGxvdHMKICAgIGZpbHRlcmVkUGxvdCA8LSBmMSArIGYyICsgZjMgKyBmNCArIGY1ICsgcGF0Y2h3b3JrOjpndWlkZV9hcmVhKCkgKwogICAgICBwYXRjaHdvcms6OnBsb3RfbGF5b3V0KGd1aWRlcyA9ICdjb2xsZWN0JywKICAgICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSAzKQogICAgZmlsdGVyZWRQbG90CiAgICAKICAgIGdnc2F2ZShwbG90ID0gZmlsdGVyZWRQbG90LCAiUGxvdHMvRmlsdGVyZWQgRm9ybWFudHMucG5nIiwKICAgICAgICAgICBoZWlnaHQgPSA2LAogICAgICAgICAgIHdpZHRoID0gOCwKICAgICAgICAgICB1bml0cyA9ICJpbiIsCiAgICAgICAgICAgc2NhbGUgPSAuOSkKICAKYGBgCgojIyBPVCB2cy4gVkFTCmBgYHtyfQpwbG90RGF0YV9JbnQgPC0gQWNvdXN0aWNEYXRhICU+JQogIGRwbHlyOjpmaWx0ZXIoIWdyZXBsKCJfcmVsIiwgU3BlYWtlcikpICU+JQogIGRwbHlyOjpncm91cF9ieShTcGVha2VyKSAlPiUKICBkcGx5cjo6bXV0YXRlKHNlZ01pbiA9IGJhc2U6Om1pbihWQVMsIHRyYW5zQWNjKSwKICAgICAgICAgICAgICAgIHNlZ01heCA9IGJhc2U6Om1heChWQVMsIHRyYW5zQWNjKSwKICAgICAgICAgICAgICAgIHJhdGluZ0F2ZyA9IG1lYW4oVkFTLCB0cmFuc0FjYywgbmEucm0gPSBUKSwKICAgICAgICAgICAgICAgIFNwZWFrZXIgPSBhcy5mYWN0b3IoU3BlYWtlciksCiAgICAgICAgICAgICAgICBFdGlvbG9neSA9IGFzLmZhY3RvcihFdGlvbG9neSkpICU+JQogIGFycmFuZ2Uoc2VnTWF4KQoKbXlfcGFsIDwtIGMoIiNmMjY0MzAiLCAiIzI3MkQyRCIsIiMyNTZlZmYiKQojIFdpdGggYSBiaXQgbW9yZSBzdHlsZQpwbG90X0ludCA8LSBnZ3Bsb3QocGxvdERhdGFfSW50KSArCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gZmN0X2lub3JkZXIoU3BlYWtlciksCiAgICAgICAgICAgICAgICAgICB4ZW5kID0gU3BlYWtlciwKICAgICAgICAgICAgICAgICAgIHkgPSBzZWdNaW4sCiAgICAgICAgICAgICAgICAgICB5ZW5kID0gc2VnTWF4LAogICAgICAgICAgICAgICAgICAgY29sb3IgPSBFdGlvbG9neSkpICsKICBnZW9tX3BvaW50KGFlcyh4ID0gU3BlYWtlciwKICAgICAgICAgICAgICAgICB5ID0gVkFTLAogICAgICAgICAgICAgICAgIGNvbG9yID0gRXRpb2xvZ3kpLAogICAgICAgICAgICAgI2NvbG9yID0gbXlfcGFsWzFdLAogICAgICAgICAgICAgc2l6ZSA9IDMsCiAgICAgICAgICAgICBzaGFwZSA9IDE5KSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IFNwZWFrZXIsCiAgICAgICAgICAgICAgICAgeSA9IHRyYW5zQWNjLAogICAgICAgICAgICAgICAgIGNvbG9yID0gRXRpb2xvZ3kpLAogICAgICAgICAgICAgI2NvbG9yID0gbXlfcGFsWzJdLAogICAgICAgICAgICAgc2l6ZSA9IDMsCiAgICAgICAgICAgICBzaGFwZSA9IDE1KSArCiAgY29vcmRfZmxpcCgpKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgdGhlbWUoCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsCiAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksCiAgKSArCiAgeGxhYigiIikgKwogIHlsYWIoIlNwZWVjaCBJbnRlbGxpZ2liaWxpdHkiKSArCiAgZ2d0aXRsZSgiU3BlZWNoIEludGVsbGlnaWJpbGl0eSIpICsKICB5bGltKGMoMCwxMDApKQpwbG90X0ludAoKbXlQYWwgPC0gYygiIzFBQUQ3NyIsICIjMTI3OUI1IiwgIiNGRkJGMDAiLCAiI0ZENzg1MyIsICIjQkYzMTc4IikKbXlTaGFwZXMgPC0gYygxNiwgMTgsIDE3LCAxNSkKCnNjYXR0ZXIxIDwtIGdncGxvdChwbG90RGF0YV9JbnQsCiAgICAgICAgICAgICAgICAgIGFlcyh4ID0gVkFTLAogICAgICAgICAgICAgICAgICAgICAgeSA9IHRyYW5zQWNjLAogICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSBFdGlvbG9neSwKICAgICAgICAgICAgICAgICAgICAgIHNoYXBlID0gRXRpb2xvZ3ksCiAgICAgICAgICAgICAgICAgICAgICBsaW5ldHlwZSA9IEV0aW9sb2d5KSkgKwogIGdlb21fcG9pbnQoKSArCiAgI2dlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRikgKwogIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSkgKwogIGNvb3JkX2NhcnRlc2lhbih4bGltID0gYygwLDEwMCksIHlsaW0gPSBjKDAsMTAwKSkgKwogIGxhYnMoeCA9ICJJbnRlbGxpZ2liaWxpdHkgKFZBUykiLCB5ID0gIkludGVsbGlnaWJpbGl0eSAoT1QpIikgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBteVBhbCkgKwogIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBteVNoYXBlcykgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgdGhlbWUoYXNwZWN0LnJhdGlvPTEsCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uPSJyaWdodCIpCgpzY2F0dGVyMiA8LSBnZ3Bsb3QocGxvdERhdGFfSW50LAogICAgICAgICAgICAgICAgICBhZXMoeCA9IFZBUywKICAgICAgICAgICAgICAgICAgICAgIHkgPSB0cmFuc0FjYywKICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gRXRpb2xvZ3ksCiAgICAgICAgICAgICAgICAgICAgICBzaGFwZSA9IEV0aW9sb2d5LAogICAgICAgICAgICAgICAgICAgICAgbGluZXR5cGUgPSBFdGlvbG9neSkpICsKICAjZ2VvbV9wb2ludCgpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEYpICsKICBnZW9tX2FibGluZShpbnRlcmNlcHQgPSAwLCBzbG9wZSA9IDEpICsKICBjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IGMoMCwxMDApLCB5bGltID0gYygwLDEwMCkpICsKICBsYWJzKHggPSAiSW50ZWxsaWdpYmlsaXR5IChWQVMpIiwgeSA9ICJJbnRlbGxpZ2liaWxpdHkgKE9UKSIpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gbXlQYWwpICsKICBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzID0gbXlTaGFwZXMpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIHRoZW1lKGFzcGVjdC5yYXRpbz0xLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbj0icmlnaHQiKQoKY29tYmluZWRTY2F0dGVyIDwtIGdnYXJyYW5nZShzY2F0dGVyMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2F0dGVyMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb21tb24ubGVnZW5kID0gRiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuY29sID0gMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBucm93ID0gMSkKY29tYmluZWRTY2F0dGVyCgpnZ3NhdmUoZmlsZW5hbWUgPSAiUGxvdHMvT1QgYW5kIFZBUyBTY2F0dGVycGxvdC5wbmciLAogICAgICAgcGxvdCA9IGNvbWJpbmVkU2NhdHRlciwKICAgICAgIGhlaWdodCA9IDIsCiAgICAgICB3aWR0aCA9IDYsCiAgICAgICB1bml0cyA9ICJpbiIsCiAgICAgICBzY2FsZSA9IDEpCgpybShzY2F0dGVyMSwgc2NhdHRlcjIsIGNvbWJpbmVkU2NhdHRlcikKYGBgCgojIyBNb2RlbCBTY2F0dGVycGxvdHMKYGBge3J9Cm1vZGVsRmlndXJlRGF0YSA8LSBBY291c3RpY0RhdGEgJT4lCiAgZHBseXI6OmZpbHRlcighZ3JlcGwoIl9yZWwiLFNwZWFrZXIpKSAlPiUKICBkcGx5cjo6c2VsZWN0KFNwZWFrZXIsIEV0aW9sb2d5LCBTZXgsIGF1dG9WU0EsIFZTQV9iLCB2b3dlbF9FRF9iLCBIdWxsX2IsIEh1bGxfYlZTRF8yNSwgSHVsbF9iVlNEXzc1LCBWQVMsIHRyYW5zQWNjKSAlPiUKICBkcGx5cjo6bXV0YXRlKFNwZWFrZXIgPSBhcy5mYWN0b3IoU3BlYWtlciksCiAgICAgICAgICAgICAgICBFdGlvbG9neSA9IGFzLmZhY3RvcihFdGlvbG9neSksCiAgICAgICAgICAgICAgICBTZXggPSBhcy5mYWN0b3IoU2V4KSkgJT4lCiAgdGlkeXI6OnBpdm90X2xvbmdlcihjb2xzID0gVkFTOnRyYW5zQWNjLCBuYW1lc190byA9ICJJbnRUeXBlIiwgdmFsdWVzX3RvID0gIkludCIpICU+JQogIGRwbHlyOjptdXRhdGUoSW50VHlwZSA9IGNhc2Vfd2hlbigKICAgIEludFR5cGUgPT0gInRyYW5zQWNjIiB+ICJPVCIsCiAgICBUUlVFIH4gIlZBUyIKICApLAogICAgICAgICAgICAgICAgSW50VHlwZSA9IGFzLmZhY3RvcihJbnRUeXBlKSkKCnlsYWJlbCA8LSAiSW50ZWxsaWdpYmlsaXR5IgpteVBhbCA8LSBjKCIjMkQyRDM3IiwgIiMxMjc5QjUiKQpteVBhbFNoYXBlIDwtIGMoMTksIDEpCgpWU0EgPC0gbW9kZWxGaWd1cmVEYXRhICU+JQogIGdncGxvdCgpICsKICBhZXMoeCA9IFZTQV9iLAogICAgICB5ID0gSW50LAogICAgICBjb2xvciA9IEludFR5cGUsCiAgICAgIHNoYXBlID0gSW50VHlwZSwKICAgICAgbGluZXR5cGUgPSBJbnRUeXBlKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IFQsIGZpbGwgPSAibGlnaHQgZ3JleSIpICsKICB4bGFiKGV4cHJlc3Npb24oIlZTQSAoQmFyayJeMioiKSIpKSArCiAgeWxhYih5bGFiZWwpICsKICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoMCwxMDApKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlID0gImJvbGQiKSwKICAgICAgICBhc3BlY3QucmF0aW89MSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBteVBhbCkgKwogIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBteVBhbFNoYXBlKSArCiAgbGFicyhjb2xvcj0iSW50ZWxsaWdpYmlsaXR5IFR5cGUiLAogICAgICAgc2hhcGUgPSAiSW50ZWxsaWdpYmlsaXR5IFR5cGUiLAogICAgICAgbGluZXR5cGUgPSAiSW50ZWxsaWdpYmlsaXR5IFR5cGUiKQoKYXV0b1ZTQSA8LSBtb2RlbEZpZ3VyZURhdGEgJT4lCiAgZ2dwbG90KCkgKwogIGFlcyh4ID0gYXV0b1ZTQSwKICAgICAgeSA9IEludCwKICAgICAgY29sb3IgPSBJbnRUeXBlLAogICAgICBzaGFwZSA9IEludFR5cGUsCiAgICAgIGxpbmV0eXBlID0gSW50VHlwZSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBULCBmaWxsID0gImxpZ2h0IGdyZXkiKSArCiAgeGxhYihleHByZXNzaW9uKCJWU0EiW0F1dG9tYXRpY10qIiAoQmFyayJeMioiKSIpKSArCiAgeWxhYih5bGFiZWwpICsKICBjb29yZF9jYXJ0ZXNpYW4oeWxpbSA9IGMoMCwxMDApKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41LCBmYWNlID0gImJvbGQiKSwKICAgICAgICBhc3BlY3QucmF0aW89MSkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBteVBhbCkgKwogIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBteVBhbFNoYXBlKSArCiAgbGFicyhjb2xvcj0iSW50ZWxsaWdpYmlsaXR5IFR5cGUiLAogICAgICAgc2hhcGUgPSAiSW50ZWxsaWdpYmlsaXR5IFR5cGUiLAogICAgICAgbGluZXR5cGUgPSAiSW50ZWxsaWdpYmlsaXR5IFR5cGUiKQoKZGlzcCA8LSBtb2RlbEZpZ3VyZURhdGEgJT4lCiAgZ2dwbG90KCkgKwogIGFlcyh4ID0gdm93ZWxfRURfYiwKICAgICAgeSA9IEludCwKICAgICAgY29sb3IgPSBJbnRUeXBlLAogICAgICBzaGFwZSA9IEludFR5cGUsCiAgICAgIGxpbmV0eXBlID0gSW50VHlwZSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBULCBmaWxsID0gImxpZ2h0IGdyZXkiKSArCiAgeGxhYigiQ29ybmVyIERpc3BlcnNpb24gKEJhcmspIikgKwogIHlsYWIoeWxhYmVsKSArCiAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKDAsMTAwKSkgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgdGhlbWUoYXNwZWN0LnJhdGlvPTEpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gbXlQYWwpICsKICBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzID0gbXlQYWxTaGFwZSkgKwogIGxhYnMoY29sb3I9IkludGVsbGlnaWJpbGl0eSBUeXBlIiwKICAgICAgIHNoYXBlID0gIkludGVsbGlnaWJpbGl0eSBUeXBlIiwKICAgICAgIGxpbmV0eXBlID0gIkludGVsbGlnaWJpbGl0eSBUeXBlIikKCkh1bGwgPC0gbW9kZWxGaWd1cmVEYXRhICU+JQogIGdncGxvdCgpICsKICBhZXMoeCA9IEh1bGxfYiwKICAgICAgeSA9IEludCwKICAgICAgY29sb3IgPSBJbnRUeXBlLAogICAgICBzaGFwZSA9IEludFR5cGUsCiAgICAgIGxpbmV0eXBlID0gSW50VHlwZSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBULCBmaWxsID0gImxpZ2h0IGdyZXkiKSArCiAgeGxhYihleHByZXNzaW9uKCJWU0EiW0h1bGxdKiIgKEJhcmsiXjIqIikiKSkgKwogIHlsYWIoeWxhYmVsKSArCiAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKDAsMTAwKSkgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgdGhlbWUoYXNwZWN0LnJhdGlvPTEpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IG15UGFsKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IG15UGFsU2hhcGUpICsKICBsYWJzKGNvbG9yPSJJbnRlbGxpZ2liaWxpdHkgVHlwZSIsCiAgICAgICBzaGFwZSA9ICJJbnRlbGxpZ2liaWxpdHkgVHlwZSIsCiAgICAgICBsaW5ldHlwZSA9ICJJbnRlbGxpZ2liaWxpdHkgVHlwZSIpCgp2c2QyNSA8LSBtb2RlbEZpZ3VyZURhdGEgJT4lCiAgZ2dwbG90KCkgKwogIGFlcyh4ID0gSHVsbF9iVlNEXzI1LAogICAgICB5ID0gSW50LAogICAgICBjb2xvciA9IEludFR5cGUsCiAgICAgIHNoYXBlID0gSW50VHlwZSwKICAgICAgbGluZXR5cGUgPSBJbnRUeXBlKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IFQsIGZpbGwgPSAibGlnaHQgZ3JleSIpICsKICB4bGFiKGV4cHJlc3Npb24oIlZTRCJbMjVdKiIgKEJhcmsiXjIqIikiKSkgKwogIHlsYWIoeWxhYmVsKSArCiAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKDAsMTAwKSkgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgdGhlbWUoYXNwZWN0LnJhdGlvPTEpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IG15UGFsKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IG15UGFsU2hhcGUpICsKICBsYWJzKGNvbG9yPSJJbnRlbGxpZ2liaWxpdHkgVHlwZSIsCiAgICAgICBzaGFwZSA9ICJJbnRlbGxpZ2liaWxpdHkgVHlwZSIsCiAgICAgICBsaW5ldHlwZSA9ICJJbnRlbGxpZ2liaWxpdHkgVHlwZSIpCgp2c2Q3NSA8LSBtb2RlbEZpZ3VyZURhdGEgJT4lCiAgZ2dwbG90KCkgKwogIGFlcyh4ID0gSHVsbF9iVlNEXzc1LAogICAgICB5ID0gSW50LAogICAgICBjb2xvciA9IEludFR5cGUsCiAgICAgIHNoYXBlID0gSW50VHlwZSwKICAgICAgbGluZXR5cGUgPSBJbnRUeXBlKSArCiAgZ2VvbV9wb2ludCgpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IFQsIGZpbGwgPSAibGlnaHQgZ3JleSIpICsKICB4bGFiKGV4cHJlc3Npb24oIlZTRCJbNzVdKiIgKEJhcmsiXjIqIikiKSkgKwogIHlsYWIoeWxhYmVsKSArCiAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKDAsMTAwKSkgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgdGhlbWUoYXNwZWN0LnJhdGlvPTEpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IG15UGFsKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IG15UGFsU2hhcGUpICsKICBsYWJzKGNvbG9yPSJJbnRlbGxpZ2liaWxpdHkgVHlwZSIsCiAgICAgICBzaGFwZSA9ICJJbnRlbGxpZ2liaWxpdHkgVHlwZSIsCiAgICAgICBsaW5ldHlwZSA9ICJJbnRlbGxpZ2liaWxpdHkgVHlwZSIpCgojIENyZWF0aW5nIE9UIFNjYXR0ZXJwbG90IEZpZ3VyZQoKc2NhdHRlciA8LSBWU0EgICsgZGlzcCArIGF1dG9WU0EgKyBIdWxsICsgdnNkMjUgKyB2c2Q3NSArCiAgcGF0Y2h3b3JrOjpwbG90X2xheW91dChndWlkZXMgPSAnY29sbGVjdCcsCiAgICAgICAgICAgICAgICAgICAgICAgICBuY29sID0gMykgJiB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikKc2NhdHRlciAKCmdnc2F2ZSgiUGxvdHMvTW9kZWxGaWd1cmUucG5nIiwgc2NhdHRlciwKICAgICAgIGhlaWdodCA9IDQuNSwKICAgICAgIHdpZHRoID0gNiwKICAgICAgIHVuaXRzID0gImluIiwKICAgICAgIHNjYWxlID0gMS4xKQpgYGAKCiMjIEZpbHRlcmluZyBhdCBEaWZmZXJlbnQgTGV2ZWxzCmBgYHtyfQp0ZXh0X3ggPC0gMTMKdGV4dF95IDwtIDguNQp4bGltcyA8LSBjKDE2LDUpCnlsaW1zIDwtIGMoOSwxKQojIEh1bGwgLSAyIFNEIC0tLS0KUGl0Y2hfUFJBQVQgPC0gbGlzdC5maWxlcyhwYXRoID0gcGFzdGUoIlByZXBwZWQgRGF0YS9FeGFtcGxlIERhdGEiLCBzZXAgPSAiIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuID0gIi5QaXRjaCIsIGlnbm9yZS5jYXNlID0gVCkgJT4lCiAgICBwYXN0ZSgiUHJlcHBlZCBEYXRhL0V4YW1wbGUgRGF0YS8iLC4sIHNlcCA9ICIiKSAlPiUKICAgIHJlYWQuZGVsaW0oLiwgaGVhZGVyID0gRikgJT4lCiAgICBkcGx5cjo6cmVuYW1lKFBpdGNoID0gVjEpICU+JQogICAgZHBseXI6Om11dGF0ZShQaXRjaCA9IGdzdWIoIi0tdW5kZWZpbmVkLS0iLE5BLFBpdGNoKSwKICAgICAgICAgICAgICAgICAgUGl0Y2ggPSBhcy5udW1lcmljKFBpdGNoKSkKCkZvcm1hbnRzX1BSQUFUIDwtIGxpc3QuZmlsZXMocGF0aCA9IHBhc3RlKCJQcmVwcGVkIERhdGEvRXhhbXBsZSBEYXRhIiwgc2VwID0gIiIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVybiA9ICJfRm9ybWFudCIsIGlnbm9yZS5jYXNlID0gVCkgJT4lCiAgICBwYXN0ZSgiUHJlcHBlZCBEYXRhL0V4YW1wbGUgRGF0YS8iLC4sIHNlcCA9ICIiKSAlPiUKICAgIHJlYWQuZGVsaW0oLiwgaGVhZGVyID0gVCkgJT4lCiAgICBkcGx5cjo6c2VsZWN0KCFjKG5mb3JtYW50cywgQjEuSHouLCBCMi5Iei4sIEIzLkh6LiwgRjQuSHouLCBCNC5Iei4sIEY1Lkh6LiwgQjUuSHouKSkgJT4lCiAgICBkcGx5cjo6cmVuYW1lKFRpbWVfcyA9IHRpbWUucy4sCiAgICAgICAgICAgICAgICAgIEYxX0h6ID0gRjEuSHouLAogICAgICAgICAgICAgICAgICBGMl9IeiA9IEYyLkh6LiwKICAgICAgICAgICAgICAgICAgRjNfSHogPSBGMy5Iei4pICU+JQogICAgZHBseXI6Om11dGF0ZShGMV9IeiA9IGlmZWxzZShGMV9IeiA9PSAwLCBOQSwgRjFfSHopLAogICAgICAgICAgICAgICAgICBGMl9IeiA9IGlmZWxzZShGMl9IeiA9PSAwLCBOQSwgRjJfSHopLAogICAgICAgICAgICAgICAgICBGM19IeiA9IGlmZWxzZShGM19IeiA9PSAwLCBOQSwgRjNfSHopKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoRjFfSHogPSBhcy5udW1lcmljKEYxX0h6KSwKICAgICAgICAgICAgICAgICAgRjJfSHogPSBhcy5udW1lcmljKEYyX0h6KSwKICAgICAgICAgICAgICAgICAgRjNfSHogPSBzdXBwcmVzc1dhcm5pbmdzKGFzLm51bWVyaWMoRjNfSHopKSwKICAgICAgICAgICAgICAgICAgVGltZV9tcyA9IFRpbWVfcyAvIDEwMDAsCiAgICAgICAgICAgICAgICAgIEYxX2tIeiA9IEYxX0h6IC8gMTAwMCwKICAgICAgICAgICAgICAgICAgRjJfa0h6ID0gRjJfSHogLyAxMDAwLAogICAgICAgICAgICAgICAgICBGM19rSHogPSBGM19IeiAvIDEwMDAsCiAgICAgICAgICAgICAgICAgIEYxX2IgPSBlbXVSOjpiYXJrKEYxX0h6KSwKICAgICAgICAgICAgICAgICAgRjJfYiA9IGVtdVI6OmJhcmsoRjJfSHopLAogICAgICAgICAgICAgICAgICBGM19iID0gZW11Ujo6YmFyayhGM19IeikpICU+JQogICAgZHBseXI6OnNlbGVjdCghVGltZV9zKSAlPiUKICAgIGRwbHlyOjpyZWxvY2F0ZShUaW1lX21zLCAuYmVmb3JlID0gRjFfSHopICU+JQogICAgY2JpbmQoLixQaXRjaF9QUkFBVCkgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKCFpcy5uYShQaXRjaCkpICU+JQogICAgZHBseXI6Om11dGF0ZShGMV9tYWQgPSAoYWJzKEYxX0h6IC0gbWVkaWFuKEYxX0h6KSkvIG1hZChGMV9IeiwgY29uc3RhbnQgPSAxLjQ4MjYpKSA+IDIuNSwKICAgICAgICAgICAgICAgICAgRjJfbWFkID0gKGFicyhGMl9IeiAtIG1lZGlhbihGMl9IeikpLyBtYWQoRjJfSHosIGNvbnN0YW50ID0gMS40ODI2KSkgPiAyLjUpICU+JQogICAgZHBseXI6OmZpbHRlcihGMV9tYWQgPT0gRkFMU0UgJiBGMl9tYWQgPT0gRkFMU0UpICU+JQogICAgZHBseXI6Om11dGF0ZShtRGlzdCA9IG1haGFsYW5vYmlzKGNiaW5kKC4kRjFfSHosIC4kRjJfSHopLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbE1lYW5zKGNiaW5kKC4kRjFfSHosIC4kRjJfSHopKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3YgPSBjb3YoY2JpbmQoLiRGMV9IeiwgLiRGMl9IeikpKSwKICAgICAgICAgICAgICAgICAgbURpc3Rfc2QgPSBhYnMoc2NhbGUobURpc3QsY2VudGVyID0gVCkpKSAlPiUKICAgICNkcGx5cjo6bXV0YXRlKG1EaXN0T3V0bGllciA9IChzdGF0czo6cGNoaXNxKG1EaXN0LCBkZj0xLCBsb3dlci50YWlsPUZBTFNFKSkgPCAuMDAxKSAlPiUKICAgIGRwbHlyOjpmaWx0ZXIobURpc3Rfc2QgPCAyKQogIAogIGMgPC0gMgogIHdoaWxlKGMgPCBOUk9XKEZvcm1hbnRzX1BSQUFUKSl7CiAgICBGb3JtYW50c19QUkFBVCRGMV9IeltjXSA8LSBpZmVsc2UoaXMubmEoRm9ybWFudHNfUFJBQVQkRjFfSHpbYy0xXSkgJiYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzLm5hKEZvcm1hbnRzX1BSQUFUJEYxX0h6W2MrMV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5BLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZvcm1hbnRzX1BSQUFUJEYxX0h6W2NdKQogICAgRm9ybWFudHNfUFJBQVQkRjJfSHpbY10gPC0gaWZlbHNlKGlzLm5hKEZvcm1hbnRzX1BSQUFUJEYyX0h6W2MtMV0pICYmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpcy5uYShGb3JtYW50c19QUkFBVCRGMl9IeltjKzFdKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOQSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGb3JtYW50c19QUkFBVCRGMl9IeltjXSkKICAgIGMgPC0gYyArIDEKICB9CiAgcm0oYykKICAKICAgIEh1bGxfYiA8LSBjSHVsbChGb3JtYW50c19QUkFBVCRGMV9iLCBGb3JtYW50c19QUkFBVCRGMl9iKQojIyMgUGxvdHRpbmcgSHVsbAogICAgICBjb252ZXhDb29yZHMgPC0gRm9ybWFudHNfUFJBQVQgJT4lCiAgICAgICAgZHBseXI6OnNlbGVjdChGMV9iLCBGMl9iKSAlPiUKICAgICAgICBhcy5tYXRyaXgoKSAlPiUKICAgICAgICBnckRldmljZXM6OmNodWxsKCkKICAgICAgY29udmV4IDwtIEZvcm1hbnRzX1BSQUFUICU+JQogICAgICAgIHNsaWNlKGNvbnZleENvb3JkcykKCiAgICAgIGh1bGxQbG90XzIgPC0gZ2dwbG90KGFlcyhGMl9iLCBGMV9iKSwKICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEgPSBGb3JtYW50c19QUkFBVCkgKwogICAgICAgIGdlb21fcG9pbnQoc2hhcGUgPSAyMSkgKwogICAgICAgIGdlb21fcG9seWdvbihkYXRhID0gY29udmV4LAogICAgICAgICAgICAgICAgICAgICBhbHBoYSA9IC41LAogICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICIjMTI3OUI1IiwKICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IE5BLAogICAgICAgICAgICAgICAgICAgICBzaXplID0gMS41KSArCiAgICAgICAgYW5ub3RhdGUoInRleHQiLCB4ID0gdGV4dF94LCB5ID0gdGV4dF95LCBsYWJlbCA9IHBhc3RlKCJIdWxsID0gIixyb3VuZChIdWxsX2IsMykpKSArCiAgICAgICAgc2NhbGVfeV9yZXZlcnNlKCkgKwogICAgICAgIHNjYWxlX3hfcmV2ZXJzZSgpICsKICAgICAgICB4bGltKHhsaW1zKSArCiAgICAgICAgeWxpbSh5bGltcykgKwogICAgICAgIHRoZW1lX2NsYXNzaWMoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgiVlNBIEh1bGwgLSAyIFNEIikpICsgeGxhYigiRjIgKGJhcmspIikgKyB5bGFiKCJGMSAoYmFyaykiKSArCiAgICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCiAgICAgIGh1bGxQbG90XzIKICAgICAgCiMgSHVsbCAtIDIuNSBTRCAtLS0tClBpdGNoX1BSQUFUIDwtIGxpc3QuZmlsZXMocGF0aCA9IHBhc3RlKCJQcmVwcGVkIERhdGEvRXhhbXBsZSBEYXRhIiwgc2VwID0gIiIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVybiA9ICIuUGl0Y2giLCBpZ25vcmUuY2FzZSA9IFQpICU+JQogICAgcGFzdGUoIlByZXBwZWQgRGF0YS9FeGFtcGxlIERhdGEvIiwuLCBzZXAgPSAiIikgJT4lCiAgICByZWFkLmRlbGltKC4sIGhlYWRlciA9IEYpICU+JQogICAgZHBseXI6OnJlbmFtZShQaXRjaCA9IFYxKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoUGl0Y2ggPSBnc3ViKCItLXVuZGVmaW5lZC0tIixOQSxQaXRjaCksCiAgICAgICAgICAgICAgICAgIFBpdGNoID0gYXMubnVtZXJpYyhQaXRjaCkpCgpGb3JtYW50c19QUkFBVCA8LSBsaXN0LmZpbGVzKHBhdGggPSBwYXN0ZSgiUHJlcHBlZCBEYXRhL0V4YW1wbGUgRGF0YSIsIHNlcCA9ICIiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm4gPSAiX0Zvcm1hbnQiLCBpZ25vcmUuY2FzZSA9IFQpICU+JQogICAgcGFzdGUoIlByZXBwZWQgRGF0YS9FeGFtcGxlIERhdGEvIiwuLCBzZXAgPSAiIikgJT4lCiAgICByZWFkLmRlbGltKC4sIGhlYWRlciA9IFQpICU+JQogICAgZHBseXI6OnNlbGVjdCghYyhuZm9ybWFudHMsIEIxLkh6LiwgQjIuSHouLCBCMy5Iei4sIEY0Lkh6LiwgQjQuSHouLCBGNS5Iei4sIEI1Lkh6LikpICU+JQogICAgZHBseXI6OnJlbmFtZShUaW1lX3MgPSB0aW1lLnMuLAogICAgICAgICAgICAgICAgICBGMV9IeiA9IEYxLkh6LiwKICAgICAgICAgICAgICAgICAgRjJfSHogPSBGMi5Iei4sCiAgICAgICAgICAgICAgICAgIEYzX0h6ID0gRjMuSHouKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoRjFfSHogPSBpZmVsc2UoRjFfSHogPT0gMCwgTkEsIEYxX0h6KSwKICAgICAgICAgICAgICAgICAgRjJfSHogPSBpZmVsc2UoRjJfSHogPT0gMCwgTkEsIEYyX0h6KSwKICAgICAgICAgICAgICAgICAgRjNfSHogPSBpZmVsc2UoRjNfSHogPT0gMCwgTkEsIEYzX0h6KSkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKEYxX0h6ID0gYXMubnVtZXJpYyhGMV9IeiksCiAgICAgICAgICAgICAgICAgIEYyX0h6ID0gYXMubnVtZXJpYyhGMl9IeiksCiAgICAgICAgICAgICAgICAgIEYzX0h6ID0gc3VwcHJlc3NXYXJuaW5ncyhhcy5udW1lcmljKEYzX0h6KSksCiAgICAgICAgICAgICAgICAgIFRpbWVfbXMgPSBUaW1lX3MgLyAxMDAwLAogICAgICAgICAgICAgICAgICBGMV9rSHogPSBGMV9IeiAvIDEwMDAsCiAgICAgICAgICAgICAgICAgIEYyX2tIeiA9IEYyX0h6IC8gMTAwMCwKICAgICAgICAgICAgICAgICAgRjNfa0h6ID0gRjNfSHogLyAxMDAwLAogICAgICAgICAgICAgICAgICBGMV9iID0gZW11Ujo6YmFyayhGMV9IeiksCiAgICAgICAgICAgICAgICAgIEYyX2IgPSBlbXVSOjpiYXJrKEYyX0h6KSwKICAgICAgICAgICAgICAgICAgRjNfYiA9IGVtdVI6OmJhcmsoRjNfSHopKSAlPiUKICAgIGRwbHlyOjpzZWxlY3QoIVRpbWVfcykgJT4lCiAgICBkcGx5cjo6cmVsb2NhdGUoVGltZV9tcywgLmJlZm9yZSA9IEYxX0h6KSAlPiUKICAgIGNiaW5kKC4sUGl0Y2hfUFJBQVQpICU+JQogICAgZHBseXI6OmZpbHRlcighaXMubmEoUGl0Y2gpKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoRjFfbWFkID0gKGFicyhGMV9IeiAtIG1lZGlhbihGMV9IeikpLyBtYWQoRjFfSHosIGNvbnN0YW50ID0gMS40ODI2KSkgPiAyLjUsCiAgICAgICAgICAgICAgICAgIEYyX21hZCA9IChhYnMoRjJfSHogLSBtZWRpYW4oRjJfSHopKS8gbWFkKEYyX0h6LCBjb25zdGFudCA9IDEuNDgyNikpID4gMi41KSAlPiUKICAgIGRwbHlyOjpmaWx0ZXIoRjFfbWFkID09IEZBTFNFICYgRjJfbWFkID09IEZBTFNFKSAlPiUKICAgIGRwbHlyOjptdXRhdGUobURpc3QgPSBtYWhhbGFub2JpcyhjYmluZCguJEYxX0h6LCAuJEYyX0h6KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xNZWFucyhjYmluZCguJEYxX0h6LCAuJEYyX0h6KSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY292ID0gY292KGNiaW5kKC4kRjFfSHosIC4kRjJfSHopKSksCiAgICAgICAgICAgICAgICAgIG1EaXN0X3NkID0gYWJzKHNjYWxlKG1EaXN0LGNlbnRlciA9IFQpKSkgJT4lCiAgICAjZHBseXI6Om11dGF0ZShtRGlzdE91dGxpZXIgPSAoc3RhdHM6OnBjaGlzcShtRGlzdCwgZGY9MSwgbG93ZXIudGFpbD1GQUxTRSkpIDwgLjAwMSkgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKG1EaXN0X3NkIDwgMi41KQogIAogIGMgPC0gMgogIHdoaWxlKGMgPCBOUk9XKEZvcm1hbnRzX1BSQUFUKSl7CiAgICBGb3JtYW50c19QUkFBVCRGMV9IeltjXSA8LSBpZmVsc2UoaXMubmEoRm9ybWFudHNfUFJBQVQkRjFfSHpbYy0xXSkgJiYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzLm5hKEZvcm1hbnRzX1BSQUFUJEYxX0h6W2MrMV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5BLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZvcm1hbnRzX1BSQUFUJEYxX0h6W2NdKQogICAgRm9ybWFudHNfUFJBQVQkRjJfSHpbY10gPC0gaWZlbHNlKGlzLm5hKEZvcm1hbnRzX1BSQUFUJEYyX0h6W2MtMV0pICYmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpcy5uYShGb3JtYW50c19QUkFBVCRGMl9IeltjKzFdKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOQSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGb3JtYW50c19QUkFBVCRGMl9IeltjXSkKICAgIGMgPC0gYyArIDEKICB9CiAgcm0oYykKICAKICAgIEh1bGxfYiA8LSBjSHVsbChGb3JtYW50c19QUkFBVCRGMV9iLCBGb3JtYW50c19QUkFBVCRGMl9iKQojIyMgUGxvdHRpbmcgSHVsbAogICAgICBjb252ZXhDb29yZHMgPC0gRm9ybWFudHNfUFJBQVQgJT4lCiAgICAgICAgZHBseXI6OnNlbGVjdChGMV9iLCBGMl9iKSAlPiUKICAgICAgICBhcy5tYXRyaXgoKSAlPiUKICAgICAgICBnckRldmljZXM6OmNodWxsKCkKICAgICAgY29udmV4IDwtIEZvcm1hbnRzX1BSQUFUICU+JQogICAgICAgIHNsaWNlKGNvbnZleENvb3JkcykKCiAgICAgIGh1bGxQbG90XzIuNSA8LSBnZ3Bsb3QoYWVzKEYyX2IsIEYxX2IpLAogICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IEZvcm1hbnRzX1BSQUFUKSArCiAgICAgICAgZ2VvbV9wb2ludChzaGFwZSA9IDIxKSArCiAgICAgICAgZ2VvbV9wb2x5Z29uKGRhdGEgPSBjb252ZXgsCiAgICAgICAgICAgICAgICAgICAgIGFscGhhID0gLjUsCiAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gIiMxMjc5QjUiLAogICAgICAgICAgICAgICAgICAgICBmaWxsID0gTkEsCiAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxLjUpICsKICAgICAgICBhbm5vdGF0ZSgidGV4dCIsIHggPSB0ZXh0X3gsIHkgPSB0ZXh0X3ksIGxhYmVsID0gcGFzdGUoIkh1bGwgPSAiLHJvdW5kKEh1bGxfYiwzKSkpICsKICAgICAgICBzY2FsZV95X3JldmVyc2UoKSArCiAgICAgICAgc2NhbGVfeF9yZXZlcnNlKCkgKwogICAgICAgIHhsaW0oeGxpbXMpICsKICAgICAgICB5bGltKHlsaW1zKSArCiAgICAgICAgdGhlbWVfY2xhc3NpYygpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJWU0EgSHVsbCAtIDIuNSBTRCIpKSArIHhsYWIoIkYyIChiYXJrKSIpICsgeWxhYigiRjEgKGJhcmspIikgKwogICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKQogICAgICBodWxsUGxvdF8yLjUKICAgICAgCiMgSHVsbCAtIDMgU0QgLS0tLQpQaXRjaF9QUkFBVCA8LSBsaXN0LmZpbGVzKHBhdGggPSBwYXN0ZSgiUHJlcHBlZCBEYXRhL0V4YW1wbGUgRGF0YSIsIHNlcCA9ICIiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm4gPSAiLlBpdGNoIiwgaWdub3JlLmNhc2UgPSBUKSAlPiUKICAgIHBhc3RlKCJQcmVwcGVkIERhdGEvRXhhbXBsZSBEYXRhLyIsLiwgc2VwID0gIiIpICU+JQogICAgcmVhZC5kZWxpbSguLCBoZWFkZXIgPSBGKSAlPiUKICAgIGRwbHlyOjpyZW5hbWUoUGl0Y2ggPSBWMSkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKFBpdGNoID0gZ3N1YigiLS11bmRlZmluZWQtLSIsTkEsUGl0Y2gpLAogICAgICAgICAgICAgICAgICBQaXRjaCA9IGFzLm51bWVyaWMoUGl0Y2gpKQoKRm9ybWFudHNfUFJBQVQgPC0gbGlzdC5maWxlcyhwYXRoID0gcGFzdGUoIlByZXBwZWQgRGF0YS9FeGFtcGxlIERhdGEiLCBzZXAgPSAiIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuID0gIl9Gb3JtYW50IiwgaWdub3JlLmNhc2UgPSBUKSAlPiUKICAgIHBhc3RlKCJQcmVwcGVkIERhdGEvRXhhbXBsZSBEYXRhLyIsLiwgc2VwID0gIiIpICU+JQogICAgcmVhZC5kZWxpbSguLCBoZWFkZXIgPSBUKSAlPiUKICAgIGRwbHlyOjpzZWxlY3QoIWMobmZvcm1hbnRzLCBCMS5Iei4sIEIyLkh6LiwgQjMuSHouLCBGNC5Iei4sIEI0Lkh6LiwgRjUuSHouLCBCNS5Iei4pKSAlPiUKICAgIGRwbHlyOjpyZW5hbWUoVGltZV9zID0gdGltZS5zLiwKICAgICAgICAgICAgICAgICAgRjFfSHogPSBGMS5Iei4sCiAgICAgICAgICAgICAgICAgIEYyX0h6ID0gRjIuSHouLAogICAgICAgICAgICAgICAgICBGM19IeiA9IEYzLkh6LikgJT4lCiAgICBkcGx5cjo6bXV0YXRlKEYxX0h6ID0gaWZlbHNlKEYxX0h6ID09IDAsIE5BLCBGMV9IeiksCiAgICAgICAgICAgICAgICAgIEYyX0h6ID0gaWZlbHNlKEYyX0h6ID09IDAsIE5BLCBGMl9IeiksCiAgICAgICAgICAgICAgICAgIEYzX0h6ID0gaWZlbHNlKEYzX0h6ID09IDAsIE5BLCBGM19IeikpICU+JQogICAgZHBseXI6Om11dGF0ZShGMV9IeiA9IGFzLm51bWVyaWMoRjFfSHopLAogICAgICAgICAgICAgICAgICBGMl9IeiA9IGFzLm51bWVyaWMoRjJfSHopLAogICAgICAgICAgICAgICAgICBGM19IeiA9IHN1cHByZXNzV2FybmluZ3MoYXMubnVtZXJpYyhGM19IeikpLAogICAgICAgICAgICAgICAgICBUaW1lX21zID0gVGltZV9zIC8gMTAwMCwKICAgICAgICAgICAgICAgICAgRjFfa0h6ID0gRjFfSHogLyAxMDAwLAogICAgICAgICAgICAgICAgICBGMl9rSHogPSBGMl9IeiAvIDEwMDAsCiAgICAgICAgICAgICAgICAgIEYzX2tIeiA9IEYzX0h6IC8gMTAwMCwKICAgICAgICAgICAgICAgICAgRjFfYiA9IGVtdVI6OmJhcmsoRjFfSHopLAogICAgICAgICAgICAgICAgICBGMl9iID0gZW11Ujo6YmFyayhGMl9IeiksCiAgICAgICAgICAgICAgICAgIEYzX2IgPSBlbXVSOjpiYXJrKEYzX0h6KSkgJT4lCiAgICBkcGx5cjo6c2VsZWN0KCFUaW1lX3MpICU+JQogICAgZHBseXI6OnJlbG9jYXRlKFRpbWVfbXMsIC5iZWZvcmUgPSBGMV9IeikgJT4lCiAgICBjYmluZCguLFBpdGNoX1BSQUFUKSAlPiUKICAgIGRwbHlyOjpmaWx0ZXIoIWlzLm5hKFBpdGNoKSkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKEYxX21hZCA9IChhYnMoRjFfSHogLSBtZWRpYW4oRjFfSHopKS8gbWFkKEYxX0h6LCBjb25zdGFudCA9IDEuNDgyNikpID4gMi41LAogICAgICAgICAgICAgICAgICBGMl9tYWQgPSAoYWJzKEYyX0h6IC0gbWVkaWFuKEYyX0h6KSkvIG1hZChGMl9IeiwgY29uc3RhbnQgPSAxLjQ4MjYpKSA+IDIuNSkgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKEYxX21hZCA9PSBGQUxTRSAmIEYyX21hZCA9PSBGQUxTRSkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKG1EaXN0ID0gbWFoYWxhbm9iaXMoY2JpbmQoLiRGMV9IeiwgLiRGMl9IeiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sTWVhbnMoY2JpbmQoLiRGMV9IeiwgLiRGMl9IeikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvdiA9IGNvdihjYmluZCguJEYxX0h6LCAuJEYyX0h6KSkpLAogICAgICAgICAgICAgICAgICBtRGlzdF9zZCA9IGFicyhzY2FsZShtRGlzdCxjZW50ZXIgPSBUKSkpICU+JQogICAgI2RwbHlyOjptdXRhdGUobURpc3RPdXRsaWVyID0gKHN0YXRzOjpwY2hpc3EobURpc3QsIGRmPTEsIGxvd2VyLnRhaWw9RkFMU0UpKSA8IC4wMDEpICU+JQogICAgZHBseXI6OmZpbHRlcihtRGlzdF9zZCA8IDMpCiAgCiAgYyA8LSAyCiAgd2hpbGUoYyA8IE5ST1coRm9ybWFudHNfUFJBQVQpKXsKICAgIEZvcm1hbnRzX1BSQUFUJEYxX0h6W2NdIDwtIGlmZWxzZShpcy5uYShGb3JtYW50c19QUkFBVCRGMV9IeltjLTFdKSAmJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXMubmEoRm9ybWFudHNfUFJBQVQkRjFfSHpbYysxXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRm9ybWFudHNfUFJBQVQkRjFfSHpbY10pCiAgICBGb3JtYW50c19QUkFBVCRGMl9IeltjXSA8LSBpZmVsc2UoaXMubmEoRm9ybWFudHNfUFJBQVQkRjJfSHpbYy0xXSkgJiYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzLm5hKEZvcm1hbnRzX1BSQUFUJEYyX0h6W2MrMV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5BLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZvcm1hbnRzX1BSQUFUJEYyX0h6W2NdKQogICAgYyA8LSBjICsgMQogIH0KICBybShjKQogIAogICAgSHVsbF9iIDwtIGNIdWxsKEZvcm1hbnRzX1BSQUFUJEYxX2IsIEZvcm1hbnRzX1BSQUFUJEYyX2IpCiMjIyBQbG90dGluZyBIdWxsCiAgICAgIGNvbnZleENvb3JkcyA8LSBGb3JtYW50c19QUkFBVCAlPiUKICAgICAgICBkcGx5cjo6c2VsZWN0KEYxX2IsIEYyX2IpICU+JQogICAgICAgIGFzLm1hdHJpeCgpICU+JQogICAgICAgIGdyRGV2aWNlczo6Y2h1bGwoKQogICAgICBjb252ZXggPC0gRm9ybWFudHNfUFJBQVQgJT4lCiAgICAgICAgc2xpY2UoY29udmV4Q29vcmRzKQoKICAgICAgaHVsbFBsb3RfMyA8LSBnZ3Bsb3QoYWVzKEYyX2IsIEYxX2IpLAogICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IEZvcm1hbnRzX1BSQUFUKSArCiAgICAgICAgZ2VvbV9wb2ludChzaGFwZSA9IDIxKSArCiAgICAgICAgZ2VvbV9wb2x5Z29uKGRhdGEgPSBjb252ZXgsCiAgICAgICAgICAgICAgICAgICAgIGFscGhhID0gLjUsCiAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gIiMxMjc5QjUiLAogICAgICAgICAgICAgICAgICAgICBmaWxsID0gTkEsCiAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxLjUpICsKICAgICAgICBhbm5vdGF0ZSgidGV4dCIsIHggPSB0ZXh0X3gsIHkgPSB0ZXh0X3ksIGxhYmVsID0gcGFzdGUoIkh1bGwgPSAiLHJvdW5kKEh1bGxfYiwzKSkpICsKICAgICAgICBzY2FsZV95X3JldmVyc2UoKSArCiAgICAgICAgc2NhbGVfeF9yZXZlcnNlKCkgKwogICAgICAgIHhsaW0oeGxpbXMpICsKICAgICAgICB5bGltKHlsaW1zKSArCiAgICAgICAgdGhlbWVfY2xhc3NpYygpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJWU0EgSHVsbCAtIDMgU0QiKSkgKyB4bGFiKCJGMiAoYmFyaykiKSArIHlsYWIoIkYxIChiYXJrKSIpICsKICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKICAgICAgaHVsbFBsb3RfMwogICAgICAKIyBIdWxsIC0gMS41IFNEIC0tLS0KUGl0Y2hfUFJBQVQgPC0gbGlzdC5maWxlcyhwYXRoID0gcGFzdGUoIlByZXBwZWQgRGF0YS9FeGFtcGxlIERhdGEiLCBzZXAgPSAiIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuID0gIi5QaXRjaCIsIGlnbm9yZS5jYXNlID0gVCkgJT4lCiAgICBwYXN0ZSgiUHJlcHBlZCBEYXRhL0V4YW1wbGUgRGF0YS8iLC4sIHNlcCA9ICIiKSAlPiUKICAgIHJlYWQuZGVsaW0oLiwgaGVhZGVyID0gRikgJT4lCiAgICBkcGx5cjo6cmVuYW1lKFBpdGNoID0gVjEpICU+JQogICAgZHBseXI6Om11dGF0ZShQaXRjaCA9IGdzdWIoIi0tdW5kZWZpbmVkLS0iLE5BLFBpdGNoKSwKICAgICAgICAgICAgICAgICAgUGl0Y2ggPSBhcy5udW1lcmljKFBpdGNoKSkKCkZvcm1hbnRzX1BSQUFUIDwtIGxpc3QuZmlsZXMocGF0aCA9IHBhc3RlKCJQcmVwcGVkIERhdGEvRXhhbXBsZSBEYXRhIiwgc2VwID0gIiIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVybiA9ICJfRm9ybWFudCIsIGlnbm9yZS5jYXNlID0gVCkgJT4lCiAgICBwYXN0ZSgiUHJlcHBlZCBEYXRhL0V4YW1wbGUgRGF0YS8iLC4sIHNlcCA9ICIiKSAlPiUKICAgIHJlYWQuZGVsaW0oLiwgaGVhZGVyID0gVCkgJT4lCiAgICBkcGx5cjo6c2VsZWN0KCFjKG5mb3JtYW50cywgQjEuSHouLCBCMi5Iei4sIEIzLkh6LiwgRjQuSHouLCBCNC5Iei4sIEY1Lkh6LiwgQjUuSHouKSkgJT4lCiAgICBkcGx5cjo6cmVuYW1lKFRpbWVfcyA9IHRpbWUucy4sCiAgICAgICAgICAgICAgICAgIEYxX0h6ID0gRjEuSHouLAogICAgICAgICAgICAgICAgICBGMl9IeiA9IEYyLkh6LiwKICAgICAgICAgICAgICAgICAgRjNfSHogPSBGMy5Iei4pICU+JQogICAgZHBseXI6Om11dGF0ZShGMV9IeiA9IGlmZWxzZShGMV9IeiA9PSAwLCBOQSwgRjFfSHopLAogICAgICAgICAgICAgICAgICBGMl9IeiA9IGlmZWxzZShGMl9IeiA9PSAwLCBOQSwgRjJfSHopLAogICAgICAgICAgICAgICAgICBGM19IeiA9IGlmZWxzZShGM19IeiA9PSAwLCBOQSwgRjNfSHopKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoRjFfSHogPSBhcy5udW1lcmljKEYxX0h6KSwKICAgICAgICAgICAgICAgICAgRjJfSHogPSBhcy5udW1lcmljKEYyX0h6KSwKICAgICAgICAgICAgICAgICAgRjNfSHogPSBzdXBwcmVzc1dhcm5pbmdzKGFzLm51bWVyaWMoRjNfSHopKSwKICAgICAgICAgICAgICAgICAgVGltZV9tcyA9IFRpbWVfcyAvIDEwMDAsCiAgICAgICAgICAgICAgICAgIEYxX2tIeiA9IEYxX0h6IC8gMTAwMCwKICAgICAgICAgICAgICAgICAgRjJfa0h6ID0gRjJfSHogLyAxMDAwLAogICAgICAgICAgICAgICAgICBGM19rSHogPSBGM19IeiAvIDEwMDAsCiAgICAgICAgICAgICAgICAgIEYxX2IgPSBlbXVSOjpiYXJrKEYxX0h6KSwKICAgICAgICAgICAgICAgICAgRjJfYiA9IGVtdVI6OmJhcmsoRjJfSHopLAogICAgICAgICAgICAgICAgICBGM19iID0gZW11Ujo6YmFyayhGM19IeikpICU+JQogICAgZHBseXI6OnNlbGVjdCghVGltZV9zKSAlPiUKICAgIGRwbHlyOjpyZWxvY2F0ZShUaW1lX21zLCAuYmVmb3JlID0gRjFfSHopICU+JQogICAgY2JpbmQoLixQaXRjaF9QUkFBVCkgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKCFpcy5uYShQaXRjaCkpICU+JQogICAgZHBseXI6Om11dGF0ZShGMV9tYWQgPSAoYWJzKEYxX0h6IC0gbWVkaWFuKEYxX0h6KSkvIG1hZChGMV9IeiwgY29uc3RhbnQgPSAxLjQ4MjYpKSA+IDIuNSwKICAgICAgICAgICAgICAgICAgRjJfbWFkID0gKGFicyhGMl9IeiAtIG1lZGlhbihGMl9IeikpLyBtYWQoRjJfSHosIGNvbnN0YW50ID0gMS40ODI2KSkgPiAyLjUpICU+JQogICAgZHBseXI6OmZpbHRlcihGMV9tYWQgPT0gRkFMU0UgJiBGMl9tYWQgPT0gRkFMU0UpICU+JQogICAgZHBseXI6Om11dGF0ZShtRGlzdCA9IG1haGFsYW5vYmlzKGNiaW5kKC4kRjFfSHosIC4kRjJfSHopLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbE1lYW5zKGNiaW5kKC4kRjFfSHosIC4kRjJfSHopKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3YgPSBjb3YoY2JpbmQoLiRGMV9IeiwgLiRGMl9IeikpKSwKICAgICAgICAgICAgICAgICAgbURpc3Rfc2QgPSBhYnMoc2NhbGUobURpc3QsY2VudGVyID0gVCkpKSAlPiUKICAgICNkcGx5cjo6bXV0YXRlKG1EaXN0T3V0bGllciA9IChzdGF0czo6cGNoaXNxKG1EaXN0LCBkZj0xLCBsb3dlci50YWlsPUZBTFNFKSkgPCAuMDAxKSAlPiUKICAgIGRwbHlyOjpmaWx0ZXIobURpc3Rfc2QgPCAxLjUpCiAgCiAgYyA8LSAyCiAgd2hpbGUoYyA8IE5ST1coRm9ybWFudHNfUFJBQVQpKXsKICAgIEZvcm1hbnRzX1BSQUFUJEYxX0h6W2NdIDwtIGlmZWxzZShpcy5uYShGb3JtYW50c19QUkFBVCRGMV9IeltjLTFdKSAmJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXMubmEoRm9ybWFudHNfUFJBQVQkRjFfSHpbYysxXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRm9ybWFudHNfUFJBQVQkRjFfSHpbY10pCiAgICBGb3JtYW50c19QUkFBVCRGMl9IeltjXSA8LSBpZmVsc2UoaXMubmEoRm9ybWFudHNfUFJBQVQkRjJfSHpbYy0xXSkgJiYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzLm5hKEZvcm1hbnRzX1BSQUFUJEYyX0h6W2MrMV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5BLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZvcm1hbnRzX1BSQUFUJEYyX0h6W2NdKQogICAgYyA8LSBjICsgMQogIH0KICBybShjKQogIAogICAgSHVsbF9iIDwtIGNIdWxsKEZvcm1hbnRzX1BSQUFUJEYxX2IsIEZvcm1hbnRzX1BSQUFUJEYyX2IpCiMjIyBQbG90dGluZyBIdWxsCiAgICAgIGNvbnZleENvb3JkcyA8LSBGb3JtYW50c19QUkFBVCAlPiUKICAgICAgICBkcGx5cjo6c2VsZWN0KEYxX2IsIEYyX2IpICU+JQogICAgICAgIGFzLm1hdHJpeCgpICU+JQogICAgICAgIGdyRGV2aWNlczo6Y2h1bGwoKQogICAgICBjb252ZXggPC0gRm9ybWFudHNfUFJBQVQgJT4lCiAgICAgICAgc2xpY2UoY29udmV4Q29vcmRzKQoKICAgICAgaHVsbFBsb3RfMS41IDwtIGdncGxvdChhZXMoRjJfYiwgRjFfYiksCiAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gRm9ybWFudHNfUFJBQVQpICsKICAgICAgICBnZW9tX3BvaW50KHNoYXBlID0gMjEpICsKICAgICAgICBnZW9tX3BvbHlnb24oZGF0YSA9IGNvbnZleCwKICAgICAgICAgICAgICAgICAgICAgYWxwaGEgPSAuNSwKICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiIzEyNzlCNSIsCiAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSBOQSwKICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEuNSkgKwogICAgICAgIGFubm90YXRlKCJ0ZXh0IiwgeCA9IHRleHRfeCwgeSA9IHRleHRfeSwgbGFiZWwgPSBwYXN0ZSgiSHVsbCA9ICIscm91bmQoSHVsbF9iLDMpKSkgKwogICAgICAgIHNjYWxlX3lfcmV2ZXJzZSgpICsKICAgICAgICBzY2FsZV94X3JldmVyc2UoKSArCiAgICAgICAgeGxpbSh4bGltcykgKwogICAgICAgIHlsaW0oeWxpbXMpICsKICAgICAgICB0aGVtZV9jbGFzc2ljKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoIlZTQSBIdWxsIC0gMS41IFNEIikpICsgeGxhYigiRjIgKGJhcmspIikgKyB5bGFiKCJGMSAoYmFyaykiKSArCiAgICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCiAgICAgIGh1bGxQbG90XzEuNQogICAgICAKIyBDb21iaW5lZCAtLS0tCiAgICAgIGdncHVicjo6Z2dhcnJhbmdlKGh1bGxQbG90XzEuNSwgaHVsbFBsb3RfMiwgaHVsbFBsb3RfMi41LCBodWxsUGxvdF8zLAogICAgICAgICAgICAgICAgICAgICAgICBuY29sID0gNCkKICAgICAgZ2dzYXZlKGZpbGVuYW1lID0gIlBsb3RzL0h1bGwgYXQgRGlmZmVyZW50IEZpbHRlcnMucG5nIiwKICAgICAgICAgICAgIGhlaWdodCA9IDMsCiAgICAgICAgICAgICB3aWR0aD0gOSwKICAgICAgICAgICAgIHVuaXRzID0gImluIiwKICAgICAgICAgICAgIHNjYWxlID0gMS4yNSkKICAgICAgCmBgYAoKIyBMaXN0ZW5lciBEZW1vZ3JhcGhpYyBJbmZvcm1hdGlvbgpgYGB7cn0KCkxpc3RlbmVyRGVtbyA8LSBMaXN0ZW5lcnMgJT4lCiAgZnVybml0dXJlOjp0YWJsZTEoYWdlLCBnZW5kZXIsIHJhY2UsIGV0aG5pY2l0eSkKCkxpc3RlbmVyRGVtbwoKYGBgCgojIFNwZWFrZXIgRGVtb2dyYXBoaWNzCgpgYGB7cn0KClNwZWFrZXJEZW1vIDwtIEFjb3VzdGljRGF0YSAlPiUKICBkcGx5cjo6c2VsZWN0KGMoU3BlYWtlciwgU2V4LCBFdGlvbG9neSkpCgpBZ2VzIDwtIHJpbzo6aW1wb3J0KCJQcmVwcGVkIERhdGEvU3BlYWtlciBBZ2VzLnhsc3giKQoKU3BlYWtlckRlbW8gPC0gZnVsbF9qb2luKFNwZWFrZXJEZW1vLCBBZ2VzLCBieSA9ICJTcGVha2VyIikKClNwZWFrZXJEZW1vSW5mbyA8LSBTcGVha2VyRGVtbyAlPiUKICBmdXJuaXR1cmU6OnRhYmxlMShTZXgsIEV0aW9sb2d5LCBBZ2UsIG5hLnJtID0gRikKClNwZWFrZXJEZW1vSW5mbwoKU3BlYWtlckRlbW8gJT4lCiAgZHBseXI6OnN1bW1hcml6ZShtZWFuX2FnZSA9IG1lYW4oQWdlLCBuYS5ybSA9IFQpLCBhZ2Vfc2QgPSBzZChBZ2UsIG5hLnJtID0gVCksIGFnZV9yYW5nZSA9IHJhbmdlKEFnZSwgbmEucm0gPSBUKSkKCmBgYAoK